Exactly-once è una bugia: progettare integrazioni per i duplicati

Tre copie dello stesso riquadro di messaggio che convergono in un unico riquadro elaborato

Da qualche parte in ogni contratto di integrazione c'è una frase del tipo "ogni ordine sarà trasmesso esattamente una volta". Non è mai stata vera, nemmeno una volta. La rete si è partizionata a metà richiesta e il mittente ha riprovato; la coda ha riconsegnato dopo il crash di un consumer; un operatore di magazzino ha premuto due volte il pulsante di esportazione. I duplicati non sono una modalità di guasto - sono meteorologia.

Chiavi di idempotenza, scelte con cura

La soluzione è vecchia e poco affascinante: ogni messaggio porta una chiave, e l'elaborazione è un no-op quando la chiave è già stata vista. Le decisioni interessanti stanno tutte nella scelta della chiave.

  • Le chiavi naturali battono quelle generate. Una sincronizzazione ordini con chiave order_id + status sopravvive alla rigenerazione dell'outbox da parte del mittente; un UUID casuale coniato al momento dell'invio no.
  • Delimitate la chiave all'effetto, non al messaggio. Se un messaggio crea una fattura e prenota le scorte, questi sono due effetti con due chiavi - altrimenti un fallimento parziale vi lascia incapaci di riprovare in sicurezza entrambi.
  • Fate scadere le chiavi deliberatamente. Un archivio di deduplicazione che cresce all'infinito è una bomba a orologeria; uno che scade troppo presto reintroduce i duplicati. Di default usiamo 3 volte l'orizzonte massimo di retry del mittente.

Il test che conta

Ogni integrazione che consegniamo supera quello che internamente chiamiamo il test del doppio tocco: riproducete l'intero log dei messaggi di ieri contro il sistema di oggi, due volte, e confrontate lo stato risultante. Se qualcosa è cambiato al secondo passaggio, la pipeline non è finita.

È un test brutale e fallisce costantemente durante lo sviluppo - sui timestamp, sui campi di audit "creato da", sui contatori di sequenza. Ogni fallimento è un punto in cui una riconsegna alle 3 del mattino avrebbe silenziosamente corrotto i dati. Molto meglio scoprirlo in fase di sviluppo che in produzione.