È successo.
DocumentUploaded
Un fatto già avvenuto.
Dai fondamentali alle sfide di produzione.
Un documento. Più consegne. Un solo effetto?
Understand → Design → Break → Investigate → Fix → Generalize
Il punto di partenza: elaborazione AI nella richiesta HTTP.
Timeout · dipendenze a runtime · picchi senza buffer
L’API accetta il lavoro. Il worker lo completa in un secondo momento.
Il client consulta lo stato del job; non attende l’elaborazione nella stessa richiesta.
La semantica conta prima del trasporto.
DocumentUploaded
Un fatto già avvenuto.
ProcessDocument
Una richiesta a un destinatario.
Envelope + payload
Può contenere un event o un command.
Nel lab: il submit genera un fatto; l’indicizzatore reagisce a DocumentUploaded.
Scegliere l’asincrono significa accettarne anche il costo.
La richiesta di accettazione resta HTTP.
Solo il lavoro lungo attraversa il broker.
Sincrono e asincrono possono convivere.
Le responsabilità sono separate; il contratto del messaggio le collega.
RabbitMQ: producer → exchange → queue → consumer. L’exchange instrada; la queue conserva.
Competing consumers e publish/subscribe risolvono problemi diversi.
Publisher confirm e consumer ACK proteggono due passaggi diversi.
Il producer invia
Il broker accetta
Il worker riceve
Il DB persiste
Il worker conferma
Durable queue + persistent message + publisher confirms.
ACK manuale dopo il lavoro. Nessuna garanzia globale implicita.
Non sono sostituti con semantiche identiche.
Exchange, binding, consegne e ACK.
Il lab usa una queue classic durevole, non replicata.
Retention, offset e replay.
Ordine per partizione; consumer group indipendenti.
Queue e fan-out come servizi distinti.
Standard e FIFO hanno proprietà differenti.
Meno dipendenze temporali. Più responsabilità distribuite.
La delivery guarantee non è la business guarantee.
Possibile perdita.
Un ACK anticipato può perdere il lavoro dopo un crash.
Duplicati possibili.
Il lab usa ACK manuali e deve tollerare la redelivery.
Chiedere sempre quale.
Transazioni del broker non coprono automaticamente API e DB esterni.
Il DB ha finito. Il broker non lo sa.
Unacked
Effetto persistito
Prima dell’ACK
Stesso messaggio
Connessione chiusa → il broker rimette in coda la consegna non confermata.
Senza idempotenza: l’effetto può ripetersi.
Tre identità rendono leggibile la dimostrazione.
Resta stabile.
BROKER MESSAGECambia al republish.
RECEIPTCambia a ogni ricezione.
Republish ≠ redelivery.
Nel secondo caso: stessa publicationId, RabbitMQ redelivered=true.
Due consumer possono osservare lo stesso “non ancora processato”.
if (!(await alreadyProcessed(event.id))) {
await applyBusinessOperation(event);
await markAsProcessed(event.id);
}A legge: assente
B legge: assente
A + B applicano l’effetto
Check e write separati lasciano una race condition.
Il vincolo unico decide chi può applicare l’effetto.
BEGIN; INSERT INTO processed_events (...) ON CONFLICT DO NOTHING RETURNING event_id; -- solo se la claim è riuscita: UPDATE documents SET operations = operations + 1; INSERT INTO operations (...); COMMIT;
Claim + effetto nella stessa transazione.
Una claim concorrente attende la decisione della prima transazione.
Unicità: (scenario_id, event_id). Dopo COMMIT, il consumer invia ACK.
Un errore transitorio e un poison message non si trattano allo stesso modo.
Prima la normalità. Poi lo stesso evento, due volte.
1 operazione · 100 unità simulate · ACK sent
2 operazioni · 200 unità simulate · nessuna redelivery
Una nuova run elimina la contaminazione tra modalità.
2 delivery · 1 effetto · 1 duplicate skipped
Start second consumer → Publish concurrent pair
COMMIT riuscito. Nessun ACK. Un nuovo processo riceve lo stesso messaggio.
Exit code 42 · riavvio automatico · redelivered=true
Stessa publicationId · nuovo PID · duplicate detected · ACK sent
Il cloud gestisce infrastruttura; l’applicazione gestisce la semantica.
Buffer, visibility timeout, redelivery.
Un topic, più sottoscrizioni.
Event bus, regole, target.
SQS: il messaggio si elimina dopo il successo.
Con Lambda: event source mapping in polling, batch e retry da progettare.
Solo confronto teorico: nessuna risorsa AWS richiesta.
Conditional write per la claim; transazione per claim + effetto.
Account, Region e limiti del servizio definiscono il confine.
Can we really guarantee that an event is processed exactly once?
Delivery del messaggio.
Esecuzione del consumer.
Effetto di business.
Il lab protegge un effetto PostgreSQL. Non ogni sistema esterno.
Prossimi passi: Inbox per deduplicare, Outbox per pubblicare con affidabilità.