V každé integrační smlouvě je někde věta jako „každá objednávka bude přenesena přesně jednou." Nebyla pravdivá ani jednou. Síť se uprostřed požadavku rozdělila a odesílatel to zkusil znovu; fronta doručila zprávu znovu po pádu konzumenta; skladník dvakrát stiskl tlačítko exportu. Duplicity nejsou porucha - jsou počasí.
Idempotentní klíče, volené s rozvahou
Řešení je staré a nevzhledné: každá zpráva nese klíč a zpracování je no-op, pokud už byl klíč jednou viděn. Všechna zajímavá rozhodnutí spočívají ve volbě klíče.
- Přirozené klíče poráží generované. Synchronizace objednávek s klíčem
order_id + statuspřežije, když si odesílatel znovu vygeneruje svůj outbox; náhodné UUID vytvořené v okamžiku odeslání ne. - Rozsah klíče vázejte na efekt, ne na zprávu. Pokud jedna zpráva vytvoří fakturu a zaúčtuje sklad, jde o dva efekty se dvěma klíči - jinak vás částečné selhání připraví o možnost bezpečně zopakovat ani jeden z nich.
- Nechte klíče záměrně expirovat. Úložiště pro deduplikaci, které roste donekonečna, je časovaná bomba; takové, které expiruje příliš brzy, znovu vpustí duplicity. Standardně nastavujeme 3× maximální horizont opakování odesílatele.
Test, na kterém záleží
Každá integrace, kterou dodáme, projde tím, čemu interně říkáme test dvojitého klepnutí: přehrajeme celý včerejší log zpráv proti dnešnímu systému, dvakrát, a porovnáme výsledný stav. Pokud se při druhém průchodu cokoliv změnilo, pipeline není hotová.
Je to brutální test a během vývoje neustále selhává - na časových razítkách, na auditních polích „vytvořil", na sekvenčních čítačích. Každé selhání je místo, kde by doručení zprávy ve tři ráno tiše poškodilo data. Mnohem levnější je zachytit to při vývoji než v produkci.