Capsule Informatiche di Lello De Luca
← Tutte le Capsule

Transactional Outbox, Inbox e Idempotenza: eventi affidabili

Outbox, Inbox e Idempotenza rendono affidabili i flussi event-driven senza richiedere transazioni distribuite tra database e broker.

Il problema del dual write

Supponiamo che ADT salvi un ricovero e poi pubblichi PatientAdmitted. Se il database fa commit ma il processo muore prima del publish, il ricovero esiste ma nessun consumer riceve l'evento. Se si pubblica prima e poi fallisce il commit, i consumer reagiscono a un fatto che non esiste. Due sistemi separati non condividono automaticamente la stessa transazione.

Transactional Outbox

La soluzione è scrivere nella stessa transazione locale sia la modifica di dominio sia un record outbox. Dopo il commit, un publisher indipendente legge l'outbox e invia il messaggio al broker. Solo dopo conferma marca l'evento come pubblicato o avanza il proprio offset.

Sequenza

  1. BEGIN transaction.

  2. Aggiorna l'aggregate, per esempio Encounter.

  3. Inserisce OutboxEvent con eventId, type, aggregateId, payload e timestamp.

  4. COMMIT: dominio ed evento diventano persistenti insieme.

  5. Outbox publisher invia l'evento a RabbitMQ.

  6. Il messaggio può essere ritentato finché non viene confermato.

Perché serve l'idempotenza

La consegna affidabile è normalmente at-least-once: lo stesso evento può arrivare più di una volta. Il consumer non deve quindi assumere unicità della consegna. Deve rendere idempotente l'effetto o memorizzare gli eventId già processati.

Inbox Pattern

Un consumer può registrare in una tabella inbox l'identificatore del messaggio dentro la stessa transazione con cui applica la modifica locale. Se riceve di nuovo lo stesso eventId, riconosce la ridelivery e non ripete l'effetto.

Idempotency Key per API

Lo stesso principio vale per comandi HTTP a rischio di retry, per esempio creazione ordine o richiesta documento. Il client invia una idempotency key; il server restituisce lo stesso risultato a richieste duplicate invece di creare due risorse.

Cose da non confondere

  • Outbox garantisce che l'intenzione di pubblicare sia persistita con la transazione di dominio.

  • Inbox/dedup protegge il consumer dalle rideliveries.

  • Retry decide quando riprovare; non sostituisce l'idempotenza.

  • Exactly-once end-to-end è spesso un'illusione costosa: progettare effetti idempotenti è più robusto.