Pular para o conteúdo principal

Pacotes, composições e Transações

Introdução

Este documento técnico detalha como utilizar o recurso Bundle do FHIR (Fast Healthcare Interoperability Resources) para realizar operações em pacote (batch) e transações através das APIs da Nilo. O Bundle é um container para uma coleção de recursos relacionados. Ele pode ser usado para diversos propósitos, incluindo o agrupamento de recursos logicamente relacionados e a execução de um conjunto de operações como uma única unidade atômica (transação) ou independente (pacote).

Conceitos Fundamentais

Um Bundle é um recurso FHIR que contém uma lista de outros recursos dentro de sua propriedade entry. Cada entrada (Bundle.entry) possui as seguintes propriedades relevantes para pacotes e transações:

  • fullUrl: Uma URI única para identificar o recurso dentro do Bundle. Isso é crucial para referenciar um recurso dentro do Bundle a partir de outro recurso no mesmo Bundle.
  • resource: O próprio recurso FHIR (por exemplo, Patient, Condition, CarePlan) que está sendo incluído no Bundle.
  • request: Detalhes sobre a operação a ser realizada para este recurso em um cenário transacional ou em lote. Isso inclui o method (POST, PUT, GET, DELETE) e a url do endpoint do recurso. Para operações de criação, o método geralmente é POST e a url é o nome do recurso (e.g., Patient, Condition). O atributo ifNoneExist pode ser utilizado com o método POST para evitar a criação de duplicados baseados em um critério de identificação.

O atributo type do recurso Bundle define como o Bundle deve ser processado:

  • batch: Indica que as operações no Bundle são independentes e podem ser processadas separadamente. Não há garantia de atomicidade.

Pacotes (Batch) de Recursos

A utilização de Bundles com o type definido como batch permite o envio de múltiplas operações para o servidor FHIR em uma única requisição HTTP. Cada entry no Bundle representa uma operação individual que será processada de forma independente.

Exemplo de Pacote (Batch):

Suponha que a Acme Saúde precise criar dois novos pacientes. Podemos agrupar as operações de criação em um Bundle do tipo batch:

{
"resourceType": "Bundle",
"type": "batch",
"entry": [
{
"fullUrl": "urn:uuid:123e4567-e89b-12d3-a456-426614174000",
"request": {
"method": "POST",
"url": "Patient",
"ifNoneExist": "identifier=https://servicos.receita.fazenda.gov.br/servicos/cpf/|01234567890"
},
"resource": {
"resourceType": "Patient",
"identifier": [
{
"system": "https://servicos.receita.fazenda.gov.br/servicos/cpf/",
"value": "01234567890"
}
],
"name": [
{
"use": "official",
"text": "Bugs Bunny"
}
],
"gender": "male",
"birthDate": "1940-07-27",
"telecom": [
{
"system": "email",
"value": "bugs.bunny@acmesaude.com.br",
"use": "work"
}
]
}
},
{
"fullUrl": "urn:uuid:987f6543-ba09-87dc-5678-0987654321ab",
"request": {
"method": "POST",
"url": "Patient",
"ifNoneExist": "identifier=https://servicos.receita.fazenda.gov.br/servicos/cpf/|98765432109"
},
"resource": {
"resourceType": "Patient",
"identifier": [
{
"system": "https://servicos.receita.fazenda.gov.br/servicos/cpf/",
"value": "98765432109"
}
],
"name": [
{
"use": "official",
"text": "Lola Bunny"
}
],
"gender": "female",
"birthDate": "1996-04-03",
"telecom": [
{
"system": "email",
"value": "lola.bunny@acmesaude.com.br",
"use": "work"
}
]
}
}
]
}

Ao enviar este Bundle com type batch, o servidor FHIR tentará criar ambos os recursos Patient de forma independente. O resultado da requisição conterá um Bundle de resposta com o status de cada operação.

Transações com Bundle

Uma outra maneira de usar pacotes é usar referências internas. A principal diferença é que o recurso que faz a referência quando for processado seja automaticamente associado pelo sistema ao recurso referenciado criado, já com a referência correta para o identifier desse novo recurso. É uma maneira prática de criar num mesmo request dois recursos diferentes e já fazer a associação entre eles.

Exemplo de Transação:

A Acme Saúde precisa registrar um novo paciente e associar uma condição médica a ele em um único pacote.

{
"resourceType": "Bundle",
"type": "batch",
"entry": [
{
"fullUrl": "urn:uuid:c0ffee00-c0de-cafe-babe-deadbeef0001",
"request": {
"method": "POST",
"url": "Patient",
"ifNoneExist": "identifier=https://servicos.receita.fazenda.gov.br/servicos/cpf/|13579086420"
},
"resource": {
"resourceType": "Patient",
"identifier": [
{
"system": "https://servicos.receita.fazenda.gov.br/servicos/cpf/",
"value": "13579086420"
}
],
"name": [
{
"use": "official",
"text": "Piu-Piu Silva"
}
],
"gender": "male",
"birthDate": "2010-05-05",
"telecom": [
{
"system": "email",
"value": "piu-piu.silva@acmesaude.com.br",
"use": "home"
}
]
}
},
{
"request": {
"method": "POST",
"url": "Condition"
},
"fullUrl": "urn:uuid:c0ffee00-c0de-cafe-babe-deadbeef0002",
"resource": {
"resourceType": "Condition",
"subject": {
"reference": "urn:uuid:c0ffee00-c0de-cafe-babe-deadbeef0001"
},
"code": {
"coding": [
{
"code": "K59.0",
"display": "Constipação",
"system": "http://hl7.org/fhir/sid/icd-10"
}
]
},
"verificationStatus": {
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/condition-ver-status",
"code": "confirmed"
}
]
}
}
}
]
}

Neste exemplo de pacote:

  1. Um recurso Patient é criado com um fullUrl único (urn:uuid:c0ffee00-c0de-cafe-babe-deadbeef0001). O bloco request especifica um POST para o endpoint Patient. O ifNoneExist garante que um novo paciente só será criado se não existir um com o CPF especificado.
  2. Um recurso Condition é criado e referencia o Patient recém-criado utilizando seu fullUrl no atributo subject.reference. O bloco request especifica um POST para o endpoint Condition.

Ao enviar este Bundle com referência interna, o servidor FHIR processará as operações sequencialmente. Se a criação do Patient for bem-sucedida, mas houver um erro ao criar a Condition, o Patient será criado, mas um erro indicará que não houve sucesso na criação da Condition.

Na resposta, virá um detalhamento com a referencia ao recurso pelo fullUrl e o erro, e os recursos criados com sucesso terão sua referencia feita pelo id.

Usando como base o exemplo acima, o retorno para o caso do paciente ser criado mas a condição de saúde não, seria:

{
"entry": [
{
"response": {
"location": "urn:uuid:c0ffee00-c0de-cafe-babe-deadbeef0002",
"outcome": {
"issue": [
{
"code": "structure",
"details": {
"text": "Resource dependencies not processed successfully"
},
"expression": [
"Bundle.entry"
],
"severity": "error"
}
],
"resourceType": "OperationOutcome"
},
"status": "400 Bad Request"
}
},
{
"response": {
"location": "Patient/fc192bbb-4970-4943-989f-586e63859985",
"status": "200 OK"
}
}
]
}

Considerações para Desenvolvedores

  • Identificadores: É fundamental utilizar identificadores únicos (identifier e fullUrl) de forma consistente dentro do Bundle para garantir referências corretas entre os recursos.
  • Referências: Ao referenciar recursos dentro do mesmo Bundle, utilize o fullUrl do recurso de destino. Para referenciar recursos existentes fora do Bundle, utilize um identificador(identifier) do recurso.
  • Tratamento de Erros: Ao realizar transações e operações em pacote, implemente mecanismos robustos para lidar com as respostas da API. Para Bundles cada entry na resposta conterá o resultado da operação individual.
  • Performance: Embora os Bundles possam otimizar o número de requisições para a API, Bundles muito grandes podem impactar a performance do sistema. Considere o tamanho e a complexidade dos Bundles ao projetar suas integrações. Recomendamos não enviar mais que 10 recursos num mesmo Bundle, idealmente, se possível, ficar em torno de 5.
  • Documentação da API: Consulte sempre a documentação oficial da API da Nilo (https://docs.nilo.services/docs/category/apis-fhir) e a especificação FHIR R4 (https://hl7.org/fhir/R4/index.html) para obter detalhes específicos sobre o suporte a Bundles e quaisquer requisitos ou limitações adicionais.

A utilização eficiente de Bundles para operações em pacote e transações permite que sejam realizadas integrações mais complexas e consistentes com outros sistemas de saúde, aproveitando ao máximo os padrões de interoperabilidade do FHIR