Sem chamadas HTTP entre APIs
Ingestão e consolidação são limites independentes. A leitura não deve depender da disponibilidade da API de escrita.
Estudo de caso arquitetural · laboratório público
O dotnet-observability-lab é uma arquitetura de referência educacional que uso para tornar verificável uma linha completa de raciocínio: problema → restrições → atributos de qualidade → decisões → implementação → falhas → observabilidade → evidências.
Esta página é uma leitura de portfólio. A documentação técnica canônica permanece no repositório do laboratório.
Problema
Uma API recebe um valor e precisa aceitá-lo de forma durável e idempotente. Em outro serviço, esse valor precisa ser consolidado de forma assíncrona, sem chamada HTTP entre APIs e sem transformar uma entrega repetida pelo broker em duplicação do efeito de negócio.
A dificuldade real não está no valor decimal. Está no intervalo entre persistir, publicar, consumir, confirmar e recuperar — inclusive quando não é possível saber com certeza se a etapa anterior terminou.
Restrições e atributos de qualidade
Ingestão e consolidação são limites independentes. A leitura não deve depender da disponibilidade da API de escrita.
O RabbitMQ pode entregar a mesma mensagem novamente. Duplicatas fazem parte do contrato e precisam ser tratadas como comportamento normal.
O PostgreSQL mantém os registros duráveis de idempotência, Outbox, Inbox e do agregado. O Redis é uma otimização, sem papel na garantia de correção.
OpenTelemetry define traces, métricas e logs. Aspire compõe e exibe o ambiente local, mas não roteia tráfego de negócio.
Decisões e trade-offs
RabbitMQ desacopla disponibilidade e latência entre ingestão e consolidação.
Trade-off: consistência eventual e maior custo operacional.
ADR 0004 ↗O valor e o evento pendente são persistidos na mesma transação; um worker publica depois com confirmação do broker.
Trade-off: consultas periódicas, novas tentativas, quarentena e possibilidade de publicação repetida.
Implementação ↗Identidade da mensagem e atualização do agregado são confirmadas na mesma transação PostgreSQL.
Trade-off: toda mensagem única exige trabalho durável e política futura de retenção.
Implementação ↗O desenho não promete exactly-once. Ele permite repetir o processamento sem duplicar o efeito de negócio.
Trade-off: cada consumidor precisa tratar identidade e duplicação explicitamente.
Contrato do evento ↗O cache reduz o custo de requisições HTTP repetidas, mas sua indisponibilidade, a expiração ou a remoção de entradas não podem comprometer a correção.
Trade-off: buscas sem resultado no cache e falhas ainda podem exigir acesso ao banco de dados.
ADR 0003 ↗Contexto W3C atravessa a fronteira assíncrona; Aspire é uma das superfícies locais de inspeção.
Trade-off: propagação e instrumentação precisam ser mantidas explicitamente.
ADR 0005 ↗Fluxo nominal
Falhas relevantes
A mesma chave com o mesmo valor retorna o recibo original; uso conflitante retorna 409. A restrição única no PostgreSQL resolve corrida concorrente.
A Inbox impede segundo efeito de negócio. A mensagem pode ser consumida mais de uma vez sem incrementar o agregado novamente.
A API ainda pode aceitar e persistir a escrita. O Outbox mantém trabalho pendente para publicação posterior.
O fast path desaparece, mas a correção não. A decisão de idempotência volta ao PostgreSQL.
O evento pode ser republicado com a mesma identidade; o consumidor trata a duplicata de forma segura.
A gravação na Inbox e a atualização do agregado são revertidas juntas. Não fica um marcador falso de processamento concluído.
Observabilidade
O contexto W3C iniciado na requisição é persistido junto ao Outbox, reiniciado pelo worker de publicação e propagado por headers AMQP até o consumidor. Métricas de baixa cardinalidade diferenciam aceitação, publicação, processamento e duplicação; logs estruturados registram resultados operacionais relevantes.
O objetivo não é “ter dashboards”. É conseguir explicar por que uma escrita ainda não apareceu no modelo de leitura e localizar a fronteira onde o fluxo está parado ou repetindo.
Ver testes de traces e métricas ↗Evidências públicas
Limites deliberados
O laboratório mantém um único PostgreSQL local com bancos lógicos separados, não define uma plataforma de implantação em produção e não implementa no v1 uma política completa de tentativas limitadas e fila de mensagens não processadas (DLQ) no consumidor. Também não promete ordenação de eventos nem exactly-once.
Esses limites são parte da evidência: mostram o que foi decidido, o que foi simplificado para fins educacionais e quais decisões precisariam ser reabertas em um sistema real.
Explorar o repositório completo ↗