Capítulo 13 — Arquitetura de Eventos e Mensageria
Este capítulo apresenta a Arquitetura de Mensageria e RabbitMQ da Plataforma de Relacionamento Digital com o Cidadão.
13.1 Objetivo do Capítulo
Este capítulo apresenta a Arquitetura de Mensageria e RabbitMQ da Plataforma de Relacionamento Digital com o Cidadão.
A adoção do RabbitMQ é uma decisão arquitetural confirmada. Ele não é utilizado apenas como mecanismo de tarefas em background — constitui a infraestrutura transversal de comunicação assíncrona da plataforma, cobrindo: publicação de eventos de domínio, execução de comandos assíncronos, distribuição de trabalhos, integração entre serviços, ingestão no Data Lake, processamento documental e ativação de capacidades não interativas de inteligência artificial.
Este capítulo define: topologia de exchanges e filas, convenções de nomenclatura, envelope de mensagens, versionamento, Publisher Confirms, Transactional Outbox, política de acknowledgment, classificação de falhas, retry, Dead Letter Queues, idempotência, segurança, isolamento multi-tenant, observabilidade e catálogo inicial de eventos.
13.2 Papel da Mensageria na Plataforma
A mensageria desacopla serviços que não precisam de resposta imediata, absorve picos de carga e habilita processamentos paralelos sem acoplamento de chamada.
Exemplo do fluxo de uma submissão de solicitação:
Request Service publica request.submitted.v1
│
▼
RabbitMQ
│
├──▶ Workflow Service → inicia instância de processo
├──▶ Communication Service → envia confirmação ao cidadão
├──▶ Analytics Service → atualiza projeção analítica
└──▶ Data Lake Ingestion → ingere evento na partição do tenant
O Request Service registra o fato sem executar diretamente nenhuma dessas ações. Cada consumidor processa o evento conforme sua responsabilidade, no seu próprio ritmo, com sua própria política de falha.
13.3 Classificação de Mensagens
A arquitetura distingue três categorias de mensagens com características e regras diferentes.
13.3.1 Eventos de Domínio
Representam fatos que já ocorreram no domínio de negócio. São imutáveis, versionsados e publicados para múltiplos consumidores independentes.
Exemplos:
request.submitted.v1
citizen.updated.v1
appointment.scheduled.v1
document.uploaded.v1
13.3.2 Comandos Assíncronos
Representam solicitações explícitas de execução direcionadas a um consumidor lógico conhecido. São processados por um único consumidor por vez.
Exemplos:
communication.send.v1
workflow.start.v1
document.process.v1
integration.sei.register.v1
ai.knowledge.index.v1
13.3.3 Trabalhos Distribuídos
Processamentos que escalam horizontalmente por workers, sem remetente único esperando resultado imediato.
Exemplos:
document.ocr.v1
document.metadata.extract.v1
ai.embedding.generate.v1
datalake.ingest.v1
report.export.v1
13.4 Topologia de Exchanges
A plataforma utiliza exchanges com responsabilidade definida. Nenhuma exchange acumula finalidades incompatíveis.
platform.events → eventos de domínio (topic)
platform.commands → comandos assíncronos (direct)
platform.work → trabalhos distribuídos (direct)
platform.dead-letter → DLX para mensagens não processáveis (fanout)
Os nomes são a referência de arquitetura. A nomenclatura definitiva por ambiente é registrada como ADR-066.
13.4.1 Exchange de Eventos (platform.events)
Tipo topic. Recebe eventos publicados pelos serviços de domínio com routing keys no formato <domínio>.<evento>.<versão>.
Bindings de consumidores usam padrão específico ou wildcard controlado:
# fila que consome só eventos de solicitação submetida
routing key: request.submitted.v1
# fila que consome qualquer evento do domínio de solicitações
routing key: request.#
Wildcards amplos como # são avaliados com cautela — bindings excessivamente abrangentes geram consumo desnecessário e dificultam rastreabilidade.
13.4.2 Exchange de Comandos (platform.commands)
Tipo direct. Direciona comandos a consumidores específicos. A routing key identifica o consumidor lógico esperado.
13.4.3 Exchange de Trabalhos (platform.work)
Tipo direct. Distribui trabalhos entre workers que escalam horizontalmente. Múltiplas instâncias do mesmo worker consomem competitivamente a mesma fila (competing consumers).
13.4.4 Dead Letter Exchange (platform.dead-letter)
Tipo fanout ou direct. Recebe mensagens após esgotamento da política de retry. Roteia para filas de DLQ identificáveis por consumidor — nunca para uma fila global única.
13.5 Filas
13.5.1 Fila por Consumidor Lógico
Quando um evento precisa ser processado por múltiplos serviços distintos, cada um possui sua própria fila vinculada ao mesmo exchange com o mesmo routing key.
Exemplo para request.submitted.v1:
workflow.request-submitted → Workflow Service
communication.request-events → Communication Service
datalake.request-events → Data Lake Ingestion
analytics.request-events → Analytics Service
Cada consumidor recebe sua cópia independente. Nenhum "compete" com os demais pelo mesmo evento.
13.5.2 Competing Consumers
Múltiplas instâncias do mesmo consumidor podem consumir competitivamente a mesma fila. Isso é o mecanismo de escala horizontal de consumers.
document.processing ← instância 1 do Document Worker
document.processing ← instância 2 do Document Worker
document.processing ← instância 3 do Document Worker
Para que funcione corretamente com competing consumers, os processadores devem ser idempotentes.
13.5.3 Quorum Queues
Quorum Queues são o tipo recomendado para filas de negócio crítico. Oferecem replicação entre nós do cluster e maior durabilidade frente a falhas de nó. Classic Queues são avaliadas apenas para casos com justificativa técnica específica.
13.6 Convenções de Nomenclatura
A nomenclatura é previsível e derivável da responsabilidade.
Routing Keys de Eventos
<domínio>.<evento>.<versão>
request.submitted.v1
citizen.updated.v1
document.uploaded.v1
appointment.cancelled.v1
task.sla-breached.v1
Routing Keys de Comandos e Trabalhos
<capacidade>.<ação>.<versão>
communication.send.v1
workflow.start.v1
document.process.v1
ai.knowledge.index.v1
datalake.ingest.v1
Nomes de Filas
<consumidor>.<propósito>
workflow.request-submitted
communication.request-submitted
datalake.request-submitted
document.processing
ai.knowledge-builder
Nomes de DLQs
<consumidor>.<propósito>.dlq
workflow.request-submitted.dlq
communication.send.dlq
document.processing.dlq
datalake.ingestion.dlq
ai.embedding.dlq
13.7 Envelope de Mensagem
Todo evento e comando publicado no RabbitMQ carrega envelope padronizado no payload JSON:
{
"id": "01956c3e-b5f2-7b3a-a4d1-8e2f0c1d9a47",
"type": "request.submitted.v1",
"version": "1",
"occurredAt": "2026-07-15T10:30:00.000Z",
"tenantId": "org-minas-secretaria-educacao",
"correlationId": "corr-a7f2-4b81-9c3d-e5f6a2b1c8d0",
"causationId": "evt-anterior-que-causou-este",
"producer": "request-service",
"schemaVersion": "1",
"payload": {
"requestId": "req-uuid",
"serviceId": "svc-uuid",
"citizenId": "cit-uuid",
"formId": "form-uuid",
"formVersion": 7,
"channel": "WEB",
"submittedAt": "2026-07-15T10:30:00.000Z"
}
}
Campos obrigatórios:
| Campo | Descrição |
|---|---|
id | Identificador único e imutável do evento |
type | Tipo com versão (domínio.evento.v1) |
version | Versão do envelope (para evolução do próprio envelope) |
occurredAt | Instante em que o fato ocorreu, em UTC |
tenantId | Tenant de origem — obrigatório em toda mensagem da plataforma |
correlationId | Identificador de rastreabilidade da cadeia de operações |
causationId | ID do evento ou comando que causou este |
producer | Nome do serviço produtor |
payload | Dados específicos do evento ou comando |
O tenantId no envelope garante que consumidores multi-tenant apliquem isolamento sem depender do payload de negócio. Um consumer que recebe mensagem sem tenantId válido rejeita sem processar.
13.8 Serialização
JSON é o formato padrão de serialização. A escolha equilibra legibilidade, diagnóstico e interoperabilidade entre serviços Java e serviços de IA.
A adoção de formato binário (Avro, Protobuf) pode ser avaliada quando houver evidência mensurável de gargalo de performance. Não se introduz complexidade de serialização binária sem necessidade demonstrada. A decisão é registrada como ADR-069.
13.9 Versionamento de Eventos
Eventos incluem versão explícita no tipo. Alterações de contrato seguem regras de compatibilidade:
Compatível — não requer nova versão:
- adicionar campo opcional ao payload;
- adicionar novo valor a enumeração quando consumidores suportam extensão;
- adicionar metadado ao envelope.
Incompatível — requer nova versão:
- remover campo existente;
- mudar tipo de campo;
- mudar semântica de campo;
- tornar campo opcional obrigatório;
- mudar unidade ou timezone sem contrato explícito.
Durante migração para nova versão, o produtor publica ambas (v1 e v2) simultaneamente por período de transição até que todos os consumidores evoluam. Consumidores antigos ignoram a nova versão; consumidores novos processam a nova e ignoram a antiga via binding específico.
13.10 Publicação
13.10.1 Componente de Publicação
O código de domínio não manipula diretamente canais RabbitMQ. Um componente de publicação padronizado é responsável por:
- serializar o payload;
- validar o envelope (campos obrigatórios);
- propagar Tenant Context e correlationId;
- definir propriedades da mensagem;
- publicar;
- tratar confirmação (Publisher Confirms);
- registrar métricas de publicação.
Fluxo lógico:
Use Case de Domínio
│
Integration Event Publisher
│
RabbitMQ Adapter
│
RabbitMQ
13.10.2 Publisher Confirms
Publicações críticas utilizam Publisher Confirms. Uma chamada de publicação que não lança exceção local não significa que a mensagem foi confirmada pelo broker — RabbitMQ pode ter falhado internamente entre o recebimento e a persistência.
Publish
│
▼
RabbitMQ
│
ACK confirmado → mensagem persistida e roteada
NACK ou timeout → tratar como falha
A integração de Publisher Confirms com o Transactional Outbox garante que a confirmação de entrega ao broker seja registrada antes de considerar o evento publicado com sucesso.
13.10.3 Mandatory Publishing
Mensagens críticas ativam mandatory=true para detectar routing sem destino. Uma mensagem publicada sem fila correspondente retorna ao produtor com basic.return. Sem esse mecanismo, a mensagem desaparece silenciosamente. Alertas são configurados para retornos de mandatory publishing.
13.11 Transactional Outbox
O padrão Transactional Outbox elimina a inconsistência entre transação confirmada e evento não publicado. É aplicado em eventos críticos originados de alterações no banco operacional.
Fluxo:
Client → Request Service
BEGIN TRANSACTION
UPDATE request SET status = 'SUBMITTED'
INSERT INTO outbox_event (id, tenant_id, type, payload, occurred_at)
COMMIT
→ resposta ao cliente: protocolo gerado
Outbox Publisher (background)
SELECT * FROM outbox_event WHERE published_at IS NULL
Publish to RabbitMQ
Publisher Confirm ACK
UPDATE outbox_event SET published_at = NOW()
Estrutura conceitual da tabela outbox:
outbox_event
id UUID
tenant_id VARCHAR
aggregate_type VARCHAR
aggregate_id UUID
event_type VARCHAR
event_version VARCHAR
payload JSONB
occurred_at TIMESTAMPTZ
created_at TIMESTAMPTZ
published_at TIMESTAMPTZ
publication_attempts INT
Publicador da Outbox:
O publicador opera por polling periódico da tabela outbox. Em ambientes com múltiplas instâncias do serviço, SKIP LOCKED (quando suportado pelo banco) ou lock controlado garante que cada registro seja publicado por apenas uma instância por vez. Duplicidade de publicação pode ocorrer em cenários de falha após commit do banco mas antes do registro de published_at — por isso consumidores são idempotentes. Eventos publicados são removidos ou arquivados por job periódico conforme política de retenção.
13.12 Consumidores
13.12.1 Acknowledgment Manual
Consumidores de negócio crítico não usam auto-acknowledgment. O ACK ocorre após processamento confirmado e resultado persistido:
Receive message
│
Validate envelope (tenantId, type, version)
│
Apply domain logic
│
Persist result
│
ACK
ACK antes do processamento significa que a mensagem pode ser perdida se o consumer falhar depois do ACK e antes de persistir o resultado.
13.12.2 Prefetch
O prefetch é configurado por perfil de consumer:
| Perfil | Prefetch | Justificativa |
|---|---|---|
| Processamento rápido (eventos de estado) | Alto (50–200) | Baixa latência, alta throughput |
| Processamento pesado (OCR, embedding) | Baixo (1–5) | Evita sobrecarregar o consumer |
| Integração com sistema externo com rate limit | Compatível com bulkhead | Respeita limite do sistema externo |
| Ingestão no Data Lake | Médio (10–50) | Balanceia throughput e memória |
O valor definitivo é derivado de testes de carga.
13.12.3 Classificação de Falhas
O consumer classifica a falha antes de decidir a ação:
Falha transitória — timeout de banco, HTTP 502/503, storage temporariamente indisponível: → retry com backoff
Falha permanente de negócio — estado inválido, recurso definitivamente inexistente, operação não permitida: → reject sem requeue, registro funcional de falha, DLQ quando necessário
Mensagem inválida — JSON malformado, schema incompatível, versão não suportada, tenantId ausente: → DLQ imediato, alerta, sem retry repetitivo
Falha desconhecida: → retry limitado, DLQ após esgotamento
13.12.4 NACK e Requeue
NACK requeue=true sem limite cria ciclo infinito de tentativas. A política de retry controla o redirecionamento — o consumer nunca reenfileira indefinidamente.
13.13 Estratégia de Retry
O retry é limitado, orientado ao tipo de falha e usa atraso progressivo.
Política de referência (valores ajustáveis por categoria):
Tentativa 1 → processamento normal
Falha transitória
│
Retry 1 → aguardar 30 segundos (TTL em retry queue 1)
│
Falha transitória
│
Retry 2 → aguardar 5 minutos (TTL em retry queue 2)
│
Falha transitória
│
Retry 3 → aguardar 30 minutos (TTL em retry queue 3)
│
Falha
│
DLQ
A implementação usa filas de retry com TTL e dead-letter configurado de volta à exchange original:
Main Queue → falha → Retry Queue 1 (TTL=30s, DLX→platform.events) → Main Queue
↓ (se falhar de novo)
Retry Queue 2 (TTL=5m, DLX→platform.events) → Main Queue
↓ (se falhar de novo)
DLQ
Retry imediato dentro do consumer (sem sair da thread) é usado apenas para falhas com latência muito curta — nunca para manter thread aguardando minutos.
13.14 Poison Messages e Dead Letter Queues
13.14.1 Poison Messages
Uma poison message falha repetidamente de forma determinística. A arquitetura impede requeue infinito. Após o limite de retentativas, a mensagem é encaminhada à DLQ correspondente. A fila principal não é bloqueada.
13.14.2 DLQs por Consumidor
Cada consumidor lógico tem sua própria DLQ. Não existe DLQ global para toda a plataforma — uma DLQ única dificultaria investigação, autorização, reprocessamento e atribuição de responsabilidade.
workflow.request-submitted.dlq → responsável: Workflow Service
communication.send.dlq → responsável: Communication Service
document.processing.dlq → responsável: Document Worker
datalake.ingestion.dlq → responsável: Data Lake Ingestion
ai.embedding.dlq → responsável: AI Builder
13.14.3 Operação de DLQ
Cada DLQ possui: responsável definido, dashboard de monitoramento, alerta de acúmulo acionável, política de retenção, processo formal de investigação e replay auditado.
O replay é uma ação deliberada, autenticada e registrada em auditoria — não uma reexecução automática sem verificação. O reprocessamento ocorre após análise da causa raiz e garantia de que a condição de falha foi resolvida.
13.15 Idempotência
13.15.1 Princípio
A plataforma assume semântica at-least-once. Uma mensagem pode ser entregue mais de uma vez em cenários de falha ou retry. Consumidores críticos são projetados para processar a mesma mensagem múltiplas vezes sem efeito duplicado.
13.15.2 Inbox Pattern
Para consumidores que exigem garantia forte de idempotência:
BEGIN TRANSACTION
INSERT INTO inbox_message (event_id, event_type, received_at)
ON CONFLICT (event_id) DO NOTHING
RETURNING id
-- se nenhuma linha retornou: mensagem já processada
APPLY domain change
COMMIT
ACK
A tabela inbox tem retenção definida conforme a janela de redelivery esperada.
13.15.3 Idempotência por Regra de Negócio
Nem toda idempotência exige tabela Inbox. Exemplos de idempotência natural:
- aplicar cancelamento a agendamento já cancelado é no-op por regra de estado;
INSERT ... ON CONFLICT DO NOTHINGem tabela com constraint de unicidade porcommand_id;- verificar versão do agregado antes de aplicar mudança.
A escolha entre Inbox formal e idempotência por regra de negócio é feita por domínio, com o critério de robustez da garantia esperada.
13.16 Tenant Context em Mensagens
O tenantId é campo obrigatório do envelope. Consumidores multi-tenant estabelecem o Tenant Context a partir do envelope antes de processar o payload — nunca confiam em campo dentro do payload de negócio como única fonte de contexto.
O trace ID e o correlation ID são propagados via properties da mensagem RabbitMQ, permitindo rastreamento distribuído entre a publicação do evento e o processamento do consumer, sem repetição no payload de negócio.
Message Properties:
x-correlation-id: corr-xyz
x-trace-parent: 00-traceid-spanid-01 (W3C Trace Context)
x-tenant-id: tenant-abc (propagado para validação)
13.17 Integração com o Data Lake
O Data Lake é alimentado exclusivamente por eventos RabbitMQ. Nenhum serviço de domínio escreve diretamente no Data Lake.
Domínio de Negócio publica evento
│
RabbitMQ platform.events
│
datalake.<domínio>-events (fila de ingestão)
│
Data Lake Ingestion Consumer
│
Valida contrato e idempotência
│
Transforma para formato analítico
│
Persiste na partição do tenant
│
Registra linhagem
A indisponibilidade do Data Lake não bloqueia transações de negócio. O acúmulo na fila de ingestão é monitorado com alerta de backlog. O processamento é retomado quando o Data Lake se recupera, com as mensagens reprocessadas na ordem da fila.
13.18 Integração com Inteligência Artificial
13.18.1 Processamentos Não Interativos
Fluxos assíncronos de IA utilizam RabbitMQ para desacoplar o acionamento do processamento:
Document Service publica document.uploaded.v1
│
AI Builder consome: ai.knowledge.index.v1
│
Extrai conteúdo
│
Gera embeddings
│
Indexa na base vetorial do tenant
│
Publica: ai.knowledge-indexed.v1
13.18.2 Chat Interativo
O chat e a busca semântica interativos permanecem síncronos (API REST ao AI Gateway). RabbitMQ não é usado para respostas onde o cidadão ou o atendente aguarda resultado imediato.
13.18.3 Isolamento por Tenant
O tenantId do envelope garante que os workers de IA processem conteúdo e escrevam em bases vetoriais do tenant correto. Um worker não mistura conteúdo de tenants diferentes mesmo consumindo a mesma fila.
13.19 Segurança
13.19.1 Autenticação por Serviço
Cada serviço usa credenciais específicas para conectar ao RabbitMQ. Não existe credencial compartilhada entre serviços. O princípio de menor privilégio define quais exchanges e filas cada serviço pode publicar e consumir.
13.19.2 TLS
O tráfego entre serviços e RabbitMQ usa TLS. mTLS é avaliado para autenticação mútua em ambientes de produção.
13.19.3 Segredos
Credenciais do RabbitMQ são gerenciadas pelo cofre de segredos. Nenhuma credencial em variável de ambiente hardcoded, arquivo de configuração versionado ou log.
13.19.4 Dados no Payload
O payload não inclui dados pessoais sensíveis além do necessário ao processamento. Identificadores são usados no lugar de dados pessoais quando o consumer pode obter o dado diretamente do serviço responsável. Payloads de IA não incluem CPF, nome completo ou dados de saúde sem necessidade funcional explícita.
13.20 Observabilidade
13.20.1 Métricas do Broker
Métricas monitoradas continuamente:
| Métrica | Descrição | Alerta |
|---|---|---|
| Queue depth | Quantidade de mensagens em fila | Crescimento sustentado |
| Oldest message age | Idade da mensagem mais antiga na fila | Supera SLA do consumer |
| Publish rate | Taxa de publicação por exchange | Anomalia em relação ao baseline |
| Consume rate | Taxa de consumo por fila | Queda em relação ao publish rate |
| Unacked messages | Mensagens entregues e não confirmadas | Acúmulo excessivo |
| DLQ depth | Mensagens na DLQ | Qualquer acúmulo acima do baseline |
| Redelivery rate | Taxa de reentrega | Acima do esperado |
| Consumer count | Quantidade de consumers ativos | Zero consumers em fila ativa |
13.20.2 Métricas do Consumer
Cada consumer emite métricas:
- tempo de processamento por tipo de mensagem;
- taxa de sucesso e falha;
- retentativas por evento;
- DLQs enviadas;
- lag estimado (oldest message age na fila).
13.20.3 Rastreamento Distribuído
O trace iniciado na requisição HTTP que gerou o evento é propagado através da mensagem RabbitMQ para o consumer. O span do consumer pertence ao mesmo trace, permitindo rastreamento ponta a ponta:
HTTP Request (Portal → API Gateway → Request Service)
[span: http-request]
│
publica evento com traceparent
│
RabbitMQ
│
Consumer (Workflow Service)
[span: amqp-consume, parent: http-request]
13.20.4 Alertas
Alertas priorizados para operação:
- DLQ com mensagens acima do baseline;
- fila sem consumers ativos;
- oldest message age acima do SLA do serviço;
- taxa de redelivery acima de threshold;
- mandatory publishing com retornos não esperados;
- consumer com taxa de falha acima do normal.
13.21 Disponibilidade e Resiliência do Broker
O cluster RabbitMQ é configurado com múltiplos nós para redundância. Quorum Queues garantem que dados de filas críticas sobrevivam à falha de um nó. A topologia de cluster (número de nós, distribuição, estratégia de storage) é registrada como parte da arquitetura de infraestrutura no Capítulo 20.
Em caso de indisponibilidade temporária do RabbitMQ:
- o Transactional Outbox retém eventos no banco operacional até que o broker se recupere;
- publishers com retry aguardam com backoff antes de desistir;
- a operação transacional do serviço não é bloqueada pelo Outbox — o evento será publicado quando o broker voltar.
13.22 Catálogo Inicial de Eventos
| Domínio | Evento | Produtor |
|---|---|---|
| Identity | identity.user.created.v1 | Identity Service |
| Identity | identity.user.blocked.v1 | Identity Service |
| Identity | identity.federated-linked.v1 | Identity Service |
| Identity | identity.authentication-succeeded.v1 | Identity Service |
| Tenant | tenant.created.v1 | Tenant Service |
| Tenant | tenant.activated.v1 | Tenant Service |
| Tenant | tenant.suspended.v1 | Tenant Service |
| Tenant | tenant.modules-changed.v1 | Tenant Service |
| Citizen | citizen.created.v1 | Citizen Service |
| Citizen | citizen.updated.v1 | Citizen Service |
| Citizen | citizen.preferences-changed.v1 | Citizen Service |
| Citizen | citizen.consent-changed.v1 | Citizen Service |
| Service Catalog | catalog.service.published.v1 | Catalog Service |
| Service Catalog | catalog.service.suspended.v1 | Catalog Service |
| Forms | form.version-published.v1 | Forms Service |
| Request | request.created.v1 | Request Service |
| Request | request.submitted.v1 | Request Service |
| Request | request.status-changed.v1 | Request Service |
| Request | request.complement-requested.v1 | Request Service |
| Request | request.complement-submitted.v1 | Request Service |
| Request | request.cancelled.v1 | Request Service |
| Request | request.completed.v1 | Request Service |
| Workflow | workflow.instance-started.v1 | Workflow Service |
| Workflow | workflow.step-completed.v1 | Workflow Service |
| Workflow | workflow.instance-completed.v1 | Workflow Service |
| Workflow | workflow.instance-failed.v1 | Workflow Service |
| Task | task.created.v1 | Task Service |
| Task | task.assigned.v1 | Task Service |
| Task | task.sla-warning.v1 | Task Service |
| Task | task.sla-breached.v1 | Task Service |
| Task | task.completed.v1 | Task Service |
| CRM | crm.interaction-created.v1 | CRM Service |
| CRM | crm.interaction-assigned.v1 | CRM Service |
| CRM | crm.interaction-closed.v1 | CRM Service |
| CRM | crm.human-assistance-requested.v1 | CRM Service |
| Communication | communication.sent.v1 | Communication Service |
| Communication | communication.delivered.v1 | Communication Service |
| Communication | communication.failed.v1 | Communication Service |
| Communication | communication.received.v1 | Communication Service |
| Document | document.uploaded.v1 | Document Service |
| Document | document.processed.v1 | Document Service |
| Document | document.processing-failed.v1 | Document Service |
| Scheduling | appointment.scheduled.v1 | Scheduling Service |
| Scheduling | appointment.rescheduled.v1 | Scheduling Service |
| Scheduling | appointment.cancelled.v1 | Scheduling Service |
| Ombudsman | ombudsman.manifestation-created.v1 | Ombudsman Service |
| Ombudsman | ombudsman.manifestation-closed.v1 | Ombudsman Service |
| Satisfaction | satisfaction.feedback-received.v1 | Satisfaction Service |
| Segmentation | segment.calculated.v1 | Segmentation Service |
| Campaign | campaign.started.v1 | Campaign Service |
| Campaign | campaign.completed.v1 | Campaign Service |
| Data Quality | data-quality.issue-detected.v1 | Data Quality Service |
| AI | ai.chat-completed.v1 | AI Gateway |
| AI | ai.feedback-received.v1 | AI Gateway |
| AI | ai.knowledge-indexed.v1 | AI Builder |
13.23 Catálogo Inicial de Comandos
| Capacidade | Comando | Consumidor Lógico |
|---|---|---|
| Comunicação | communication.send.v1 | Communication Service |
| Workflow | workflow.start.v1 | Workflow Service |
| Documento | document.process.v1 | Document Worker |
| Documento | document.ocr.v1 | OCR Worker |
| IA | ai.knowledge.index.v1 | AI Builder |
| IA | ai.knowledge.reindex.v1 | AI Builder |
| IA | ai.summarize.v1 | AI Service |
| Integração | integration.sei.register.v1 | SEI Adapter |
| Data Lake | datalake.ingest.v1 | Ingestion Consumer |
| Relatório | report.export.v1 | Export Worker |
13.24 Decisões Confirmadas
- RabbitMQ é a infraestrutura de mensageria da plataforma;
- eventos são diferenciados de comandos e de trabalhos;
- o Tenant Context é propagado em todas as mensagens via envelope;
- eventos críticos possuem identificador único e imutável;
- consumidores críticos são idempotentes;
- retry infinito não é permitido — DLQ após esgotamento;
- o Data Lake é alimentado exclusivamente por eventos RabbitMQ;
- processamentos não interativos de IA usam filas;
- chat interativo permanece síncrono;
- arquivos binários não são transportados no payload — apenas referências;
- mensagens são versionadas com versão no tipo;
- Publisher Confirms são usados em fluxos críticos;
- Transactional Outbox garante consistência entre banco e evento;
- a semântica de entrega é
at-least-once; - observabilidade é aplicada ao broker e a cada consumer.
13.25 Benefícios da Arquitetura de Mensageria
- desacoplamento entre produtores e consumidores;
- absorção de picos sem pressão sobre serviços de domínio;
- processamento paralelo por múltiplos consumidores independentes;
- escalabilidade horizontal de workers por fila;
- resiliência por retry e DLQ sem bloqueio da fila principal;
- rastreabilidade ponta a ponta por correlationId e trace propagados;
- isolamento de tenant em toda a cadeia assíncrona;
- alimentação desacoplada do Data Lake;
- separação entre fluxos interativos (síncronos) e não interativos (assíncronos) de IA.
13.26 Riscos e Mitigações
| Risco | Consequência | Mitigação |
|---|---|---|
| Consumer não idempotente | Duplicidade de protocolos, comunicações e tarefas | Inbox Pattern ou idempotência por regra de negócio em todos os consumers críticos |
| Evento sem tenantId | Processamento em contexto errado ou rejeição silenciosa | Validação obrigatória de tenantId no consumer antes de processar |
| DLQ sem processo operacional | Mensagens acumulam sem investigação ou resolução | Owner, dashboard, alerta e runbook para cada DLQ |
| Retry storm | Cascata de falhas amplificada por retentativas | Retry budget, backoff exponencial com jitter, circuit breaker no consumer |
| Poison message bloqueando fila | Consumer parado, backlog crescente | Limite de retentativas, DLQ automático, alerta de consumer count zero |
| Mensagem sem fila correspondente | Perda silenciosa de evento crítico | Mandatory publishing com alerta de retorno |
| Outbox não publicado após falha | Evento perdido após commit do banco | Publisher com retry, monitoramento da tabela outbox por mensagens antigas |
| Dados pessoais no payload | Exposição desnecessária em logs e traces | Política de payload mínimo, revisão de contrato no pipeline |
13.27 Decisões Arquiteturais
| ADR | Tema |
|---|---|
| ADR-064 | RabbitMQ como barramento assíncrono da plataforma |
| ADR-065 | Separação entre eventos, comandos e trabalhos |
| ADR-066 | Topologia de exchanges e convenção de nomenclatura |
| ADR-067 | Formato de routing keys e convenção de nomes de filas |
| ADR-068 | Envelope padrão de mensagens |
| ADR-069 | Serialização JSON vs. formato binário |
| ADR-070 | Política de versionamento de eventos e compatibilidade |
| ADR-071 | Publisher Confirms — escopo de aplicação |
| ADR-072 | Transactional Outbox — implementação e publisher |
| ADR-073 | Inbox Pattern — escopo de aplicação por consumer |
| ADR-074 | Política de retry por categoria de consumer |
| ADR-075 | Dead Letter Queues — topologia e processo operacional |
| ADR-076 | Processo de replay de mensagens em DLQ |
| ADR-077 | Quorum Queues vs. Classic Queues por categoria |
| ADR-078 | Propagação de Tenant Context em mensagens |
| ADR-079 | Propagação de Trace Context (W3C) em RabbitMQ |
| ADR-080 | Segurança de acesso ao broker (credenciais, TLS, mTLS) |
| ADR-081 | Integração entre RabbitMQ e Data Lake |
| ADR-082 | RabbitMQ nos fluxos assíncronos de IA |
13.28 Rastreabilidade com o Anexo III
- Bloco 1 — Relacionamento e Atendimento: eventos de interação (CRM), comandos de comunicação, callbacks de canais externos, distribuição de atendimento.
- Bloco 2 — BPM:
request.submitted.v1→workflow.start.v1; eventos de tarefas; timers de SLA; integração assíncrona com sistemas externos. - Bloco 3 — Gestão Documental:
document.uploaded.v1→ workers de OCR e extração;ai.knowledge.index.v1→ builder de RAG. - Bloco 4 — Dados e Inteligência: ingestão no Data Lake por eventos de todos os domínios; indexação de bases de conhecimento; métricas de consumo de IA.
- Bloco 5 — Integração: comandos assíncronos para adaptadores externos; replay de integrações falhas; desacoplamento por DLQ.
- Bloco 6 — Infraestrutura e Governança: segregação por ambiente, credenciais por serviço, menor privilégio, contratos versionados, observabilidade, auditoria de replay.
13.29 Considerações Finais
RabbitMQ é o eixo da comunicação assíncrona da plataforma. A topologia de exchanges diferenciadas por categoria, o envelope padronizado com Tenant Context obrigatório, o Transactional Outbox para consistência, a política de retry com classificação de falhas, as DLQs por consumidor com processo operacional definido e a observabilidade end-to-end constituem a base que garante resiliência, isolamento multi-tenant e rastreabilidade em toda a cadeia assíncrona.
O Capítulo 14 detalha a Arquitetura de APIs e Integrações, descrevendo os contratos HTTP, o API Gateway, os padrões REST e os adaptadores para sistemas governamentais externos.
13.30 Controle de Versão
| Campo | Valor |
|---|---|
| Documento | Documento Mestre — Plataforma de Relacionamento Digital com o Cidadão |
| Capítulo | 13 — Arquitetura de Mensageria e RabbitMQ |
| Versão | 1.0 |
| Situação | Concluído |
| Última atualização | 15/07/2026 |
13.31 Rastreabilidade PRODEMGE
- [ANX-IV] — Capacidades técnicas de mensageria, processamento assíncrono, resiliência e escalabilidade horizontal atendidas por RabbitMQ.
- [ANX-V] — Sustentabilidade: contratos versionados, Transactional Outbox, padrões corporativos de consumer, observabilidade integrada e evolução incremental da topologia.
- [PNR] — Plano de Negócio Referencial: integração com sistemas governamentais (SEI!MG, MG-Ouv) por adaptadores acionados por comandos assíncronos; Data Lake alimentado por eventos; IA com processamentos não interativos desacoplados.
- [EDITAL] — Edital CP001/2026: arquitetura distribuída, escalável, resiliente e interoperável — propriedades sustentadas pela mensageria descrita neste capítulo.
Capítulo 12 — Arquitetura de Microsserviços
Este capítulo apresenta a Arquitetura de Microsserviços da Plataforma de Relacionamento Digital com o Cidadão, detalhando como os domínios funcionais definidos nos capítulos anteriores são decompostos em serviços backend…
Capítulo 14 — Arquitetura de APIs e Integrações
Este capítulo estabelece as diretrizes técnicas para exposição, consumo, governança, segurança, versionamento e observabilidade das interfaces de integração da Plataforma de Relacionamento Digital com o Cidadão.