Entre o envio e a confirmação.
Uma reserva foi criada. Um evento seguiu para outro componente. A confirmação se perdeu. O que acontece quando tentamos novamente? Explore os estados do experimento e reproduza cada falha localmente.
01 / As duas fronteiras
Em contraste com uma chamada síncrona no mesmo processo, aqui há duas bases, um limite HTTP e dois commits independentes. Por isso, um retorno HTTP pode se perder depois que o consumidor já gravou o efeito.
02 / A falha passo a passo
Abra os estados abaixo para acompanhar o teste de recuperação. O exemplo representa a execução automatizada do repositório, não uma simulação ao vivo no site.
S0 / COMMIT Reserva e outbox persistidos
O produtor escreve reserva e evento pendente dentro de uma transação SQLite. Falhar entre os dois INSERTs provoca rollback e não deixa uma reserva órfã.
S1 / ENTREGA POST para o consumidor
O despachante envia o evento para HTTP de loopback. O consumidor usa outra base SQLite e uma chave única para reconhecer a identidade da mensagem e realizar a deduplicação.
S2 / FALHA O efeito foi gravado, mas o ack não
O consumidor confirma seu commit. Antes de registrar o reconhecimento localmente, o despachante simula uma queda. O evento continua pendente na outbox.
S3 / REINÍCIO Reabrir os dois bancos
Novas instâncias dos repositórios SQLite leem os estados persistidos. O produtor vê uma mensagem ainda não confirmada; o consumidor já possui a notificação.
S4 / RETRY Segunda entrega, um efeito
O produtor reenvia. O consumidor encontra o event_id existente e responde como duplicata sem inserir outra notificação. Só então o produtor confirma sua outbox.
03 / Contratos observáveis
| Cenário | Estado após falha | Resultado esperado no teste |
|---|---|---|
| Falha dentro da transação | Sem reserva, sem evento | Rollback atômico |
| Falha antes do POST | Evento pendente | Entrega posterior possível |
| Commit remoto antes da confirmação local | Evento pendente, efeito remoto gravado | Retry com consumidor idempotente |
| Payload contraditório para mesmo ID | Evento não confirmado | HTTP 409, sem sobrescrever efeito |
04 / Reproduzir a bancada
Python 3.11+ e Node 20+, sem serviços externos nem dependências de runtime.
python -m unittest discover -s \
Cerberus/experiments/03-delivery-boundaries/sqlite_http \
-p 'test_*.py' -v
cd Cerberus && npm test