Proposta 1 — Transactional Outbox + Captura XStream Customizada para o Dual Write do CRM Legado (ATD)¶
Status: Brainstorming de consultoria — ver aviso metodológico Resolve: dual write entre a base ATD (Oracle 19) e o Kafka nos microsserviços de ocorrência técnica — risco R08 Recomendação: piloto em 1 fluxo (Abertura de Ocorrência Técnica) antes de generalizar — ver seção final
Contexto¶
A Ata 09 identifica dual write como um dos três temas centrais de risco do ecossistema de atendimento (item 1.10.3, síntese do assessment): "a consistência entre o dado e o evento é garantida por controle em código, e não por um padrão transacional, o que deixa espaço para falhas silenciosas". O caso concreto já registrado (item 1.10.6.6): uma ocorrência cancelada no DMS não teve o cancelamento propagado ao Sigode, exigindo carga manual de dados para restabelecer a consistência — "não é possível mapear todos os casos em que isso ocorreu".
O mesmo padrão existe do lado da base ATD (Oracle 19, confirmado no item 1.10.14.1 e no Anexo B da Ata), gravada diretamente por três microsserviços:
MsAttOcorrenciaTecnica— grava a comunicação (ATT_LIGACOES,PROTOCOLO_ATENDIMENTO, ...) e republica emcrm_registra_ocorrencia_sistema_tecnicocomo duas operações independentes. Já existe uma mitigação parcial (item 1.10.6.3): a confirmação no banco só ocorre depois da confirmação do Kafka, reduzindo a janela de inconsistência — mas não a elimina, porque a falha ainda pode ocorrer entre a confirmação do Kafka e a confirmação do banco, e o padrão não é uniforme nos demais serviços.MsAttComunicacao— grava emATD(att_ligacao,att_interacao,comunicacoes, ...) a partir do que consome decrm_comunicacao.MsAttDesligamentoEmergencial— faz upsert emDESLIGAMENTO_EMGCL_OCORC_TECNCa partir decrm_clientes_afetados_desligamento_emergencial.
A própria Energisa já reconheceu o padrão Transactional Outbox como a estratégia adequada (item 1.10.17.7 da Ata) e registrou como ação do plano (item 1.10.19, ação 10): "Avaliar e prototipar o padrão Outbox nos pontos de dual write". Esta proposta detalha um caminho concreto para essa ação, do lado Oracle da cadeia.
Fora de escopo desta proposta: o mesmo problema existe do lado do Sigode (MongoDB) — mecanismo de captura diferente (MongoDB Change Streams, não XStream), já mencionado na própria Ata (item 1.10.6.4) como alternativa a polling sobre a coleção de outbox. Tratar em proposta separada, se e quando o lado Mongo entrar em escopo.
Diagrama — Abertura de Ocorrência Técnica: hoje vs. proposta¶
Design patterns aplicados¶
| Padrão | Papel nesta proposta |
|---|---|
| Transactional Outbox | INSERT na tabela de outbox na mesma transação da gravação de negócio — elimina o dual write pela raiz, sem depender de ordem de confirmação entre duas operações independentes |
| Event Archive via CDC (XStream) | O outbox deixa de ser lido por polling ou publicado diretamente pelo serviço — um capturador externo lê a mudança via redo log e publica no Kafka, desacoplando a garantia de entrega da disponibilidade do Kafka no momento da transação |
| Cliente XStream Out customizado | Decisão explícita de não usar Debezium nem um conector comercial — ver seção "Por que customizado" abaixo, incluindo o trade-off de esforço que essa escolha carrega |
| Idempotent Producer | O producer Kafka do capturador roda com enable.idempotence=true, evitando duplicata em retry de rede na publicação |
Por que XStream customizado, e não Debezium ou conector comercial¶
A Ata 09 já cita o GoldenGate como referência de mecanismo de captura sobre Oracle (item 1.10.6.5). O licenciamento não é um obstáculo novo: a Energisa já opera XStream com Debezium em produção alimentando Kafka, com anuência confirmada da Oracle de que esse uso está em conformidade com o ULA — o que está licenciado é a API XStream em si, não um cliente específico.
Dito isso, esta proposta assume deliberadamente código customizado em vez de reaproveitar o Debezium já provado em produção — e essa escolha carrega um custo real que não deveria ser aceito sem uma razão concreta:
- Debezium (adaptador XStream) é a opção de menor esforço. Checkpoint/posição, reconexão, conversão de LCR e integração com Schema Registry já vêm prontos. Reutiliza exatamente o padrão já operado e já homologado com a Oracle em outro fluxo de produção.
- Código customizado só se justifica por um motivo concreto e explícito — por exemplo, evitar operar mais um cluster/plugin de Kafka Connect especificamente para este domínio, ou algum requisito de captura que o adaptador XStream do Debezium não cubra. Nenhum desses motivos está evidenciado nas sessões desta Ata; se não houver um, a recomendação técnica objetiva seria Debezium, não código próprio.
Esta proposta segue com a variante customizada porque foi assim que a discussão de consultoria a formulou — mas a comparação acima precisa ser levada explicitamente a quem for decidir, não decidida por omissão.
Cenários de aplicação¶
| Cenário | Proposta se aplica? |
|---|---|
| Dual write entre gravação em ATD e publicação no Kafka, sem padrão transacional | Sim — é exatamente o caso de MsAttOcorrenciaTecnica, MsAttComunicacao e MsAttDesligamentoEmergencial |
| Necessidade de eliminar a mitigação frágil de "commit só depois do Kafka confirmar" | Sim — a atomicidade passa a vir do INSERT no outbox, não da ordem de confirmação entre dois sistemas |
| Dual write do lado do Sigode (MongoDB) | Não — mecanismo de captura diferente (Change Streams), fora de escopo aqui |
| Lógica de negócio dos microsserviços (regra de cancelamento terminal, item 1.10.5.3) | Não — problema distinto, já endereçado como ação separada na Ata 09 |
Riscos e ressalvas¶
- Esforço de engenharia real, não configuração. Diferente de um conector Kafka Connect declarativo, um cliente XStream Out customizado precisa resolver, em código próprio: filtro de captura na origem (
DBMS_XSTREAM_ADM, regra restrita à tabela de outbox — sem isso o Outbound Server minera redo de tabelas irrelevantes), checkpoint/LWM explícito (confirmar posição cedo demais arrisca perder evento antes do publish; tarde demais retém redo log no banco), reconexão com retomada de posição, mapeamento deRowLCRpara o envelope de evento, e observabilidade de lag de captura (sem isso, uma captura travada só aparece quando o outbox cresce sem publicar). - Licenciamento a confirmar para este uso específico. A anuência já obtida cobre XStream via Debezium num fluxo de produção existente — vale confirmar explicitamente que o mesmo ULA cobre um cliente customizado, não apenas o Debezium já homologado.
- Escopo parcial. Resolve só o lado Oracle/ATD do dual write do ecossistema de atendimento. O lado Sigode/MongoDB, que é onde está registrado o incidente real mais concreto (cancelamento não propagado), precisa de proposta própria.
- Nenhum stakeholder pediu customizado especificamente. A ação 10 do plano da Ata 09 pede "avaliar e prototipar Outbox" — não especifica o mecanismo de captura. A escolha por código customizado em vez de Debezium é desta proposta, não um requisito articulado pela Energisa.
Recomendação¶
Piloto em um único fluxo — Abertura de Ocorrência Técnica (MsAttOcorrenciaTecnica), por ser o mais bem documentado (Diagrama 2 de fluxos-atendimento-adms.md) e já ter uma mitigação parcial em produção para comparar antes/depois. Antes de generalizar aos outros dois microsserviços, medir o esforço real de construir e operar o capturador customizado contra o esforço de simplesmente estender o Debezium já em produção para este fluxo — e decidir com esse dado em mãos, não por preferência a priori.
Ver também¶
- Ata 09 — Integrações do ADMS e DMS com Canais Digitais e Atendimento Convencional — itens 1.10.6 (dual write), 1.10.14.1 (Oracle 19), 1.10.17.7 e 1.10.19 (ação 10)
- Fluxos de Integração ADMS × Atendimento — Diagrama 2, fluxo real de Abertura de Ocorrência Técnica
- Matriz de riscos consolidada — R08
- Plano de trabalho — Fase 3 (validação) e Fase 4 (To-Be)