Pular para conteúdo

Proposta 1 — Outbox + Knative Eventing + Inbox + RabbitMQ DLQ

Status: Brainstorming de consultoria — ver aviso metodológico Resolve: dual-write, ausência de retry/DLQ ordenado, redrive artesanal (achados de integracao-wfm-eforce-ordem-servico.md)

Contexto

O eForce Worker grava estado da Ordem de Serviço no MongoDB e, hoje, publica eventos de forma não-atômica em relação a essa gravação — a discussão em chat identificou isso como dual-write clássico: se o processo cair entre a gravação e a publicação, o evento simplesmente não sai, sem qualquer mecanismo de correção além de redrive manual observado pelo próprio desenvolvedor do eForce. Não há DLQ, então uma mensagem problemática bloqueia a partition inteira do Kafka até intervenção manual.

Como o fluxo é majoritariamente intra-domínio (WFM/eForce), a proposta usa o MongoDB — que já é o store primário do eForce — como origem de verdade do Outbox, evitando introduzir uma dependência transacional externa.

Diagrama C4 — Contêineres

Proposta 1 — Outbox + Knative + Inbox + RabbitMQ DLQ

Design patterns aplicados

Padrão Papel nesta proposta
Transactional Outbox Transaction Table + Outbox Table gravadas na mesma transação Mongo — elimina o dual-write, a causa raiz do gap identificado na sessão
Change Data Capture (via Change Streams) Relay lê a Outbox Table sem acoplamento direto ao código de escrita, publicando no Kafka de forma assíncrona
Soft delete + TTL parcial Linhas da Outbox marcadas published em vez de removidas de imediato; índice TTL parcial só sobre linhas já publicadas, preservando auditoria por uma janela
Inbox / Idempotent Consumer Necessário porque a entrega do Outbox é at-least-once — sem Inbox, o Worker reprocessaria eventos duplicados após qualquer retry
Ordered delivery por partition key Knative Kafka Broker usa a extensão CloudEvents de partitioning para garantir ordenação por numeroOS — sem isso, duas atualizações da mesma OS poderiam ser aplicadas fora de ordem
Dead Letter Exchange + TTL (retry ladder) RabbitMQ escolhido para a DLQ em vez de mais tópicos Kafka — decisão deliberada para não amplificar a pressão de custo já documentada (~120 cores dedicados ao barramento, achado da Ata 10)

Cenários de aplicação

Cenário Proposta se aplica?
Eventos intra-domínio, precisam ordenação por chave de negócio (ex.: número da OS) Sim — é o caso central desta proposta
Domínio já usa MongoDB como store primário Sim — Outbox aproveita a transação nativa do Mongo, sem infraestrutura extra
Domínio persiste primariamente em Oracle (ex.: microsserviços de Atendimento) Não diretamente — nesse caso Oracle AQ/TxEventQ dá atomicidade de graça com a escrita de negócio, sem precisar de Outbox (ver recomendação já registrada por Castellani na sessão de 24/07, addendum à Ata 09)
Necessidade de reconstruir o estado de um agregado a partir do histórico completo de eventos Não — isso é Event Sourcing (Proposta 2), não Outbox
Necessidade de arquivar eventos para consulta/replay histórico de longo prazo Não é o foco desta proposta — ver Proposta 3 (complementar, não concorrente)

Riscos e trade-offs em aberto

  • Knative/OpenShift Serverless: capacidade da plataforma existe (é Kubernetes), mas o checklist de licenciamento registra zero evidência de uso ou licenciamento confirmado até 14/08/2026 — pré-requisito a validar antes de qualquer prova de conceito.
  • Latência do Relay: Change Streams introduz uma etapa de polling entre a gravação e a publicação — não é síncrono como um dual-write ingênuo, mas também não é zero-latência.
  • Novo componente operacional: RabbitMQ para DLQ significa mais um broker para operar, monitorar e dar suporte, mesmo que a decisão evite amplificar custo de tópicos Kafka.
  • Sem validação de campo: nenhuma parte desta proposta foi discutida com a equipe de barramento nem com o desenvolvedor do eForce — é ponto de partida técnico, não solução acordada.