Praktický návod
Jak automatizovat zpracování objednávek
Řiď objednávku explicitním workflow a pomalé vedlejší efekty předávej spolehlivým workerům.
Nejdřív stručně
Stav je fakt, automatizace je reakce
Objednávka má malý počet povolených stavů a přechodů. E-mail, export do ERP nebo vytvoření zásilky jsou reakce na událost, ne další nejasné hodnoty ve sloupci status.
Datovou změnu a zápis události spoj v jedné databázové transakci. Zprávy pak může bezpečně zpracovat fronta i po dočasném výpadku externí služby.
Připrav si
Popiš proces dřív než kód
Automatizace bez vlastníka a hranic končí skriptem, který mění objednávku z několika míst zároveň.
- Diagram stavů, povolených přechodů a podmínek, kdo je smí vyvolat.
- Seznam vedlejších efektů: platba, sklad, doprava, doklad, ERP a komunikace se zákazníkem.
- Jednoznačná ID objednávek, událostí a pokusů o zpracování.
- Frontu s acknowledgement, retry, dead-letter queue a monitoringem workerů.
Kroky 1 až 3
Odděl rozhodnutí od provedení
Synchronně rozhodni a ulož nový stav. Vše, co může trvat nebo selhat, dokonči asynchronně.
1. Vytvoř stavový automat
- Použij stavy například new, awaiting_payment, paid, picking, shipped a cancelled; jejich význam napiš jako obchodní pravidlo.
- Každý přechod má guard podmínky. Paid vyžaduje potvrzenou platbu, shipped existující zásilku a cancelled respektuje již expedované položky.
- Přechod provádí jediný aplikační use-case. Controller, cron ani worker nesmí stav přepsat napřímo.
- Historii změn ukládej zvlášť se starým a novým stavem, důvodem, aktérem a časem.
php bin/console workflow:dump order Oficiální Symfony Workflow dokumentace 2. Ulož změnu a událost atomicky
- Po úspěšném přechodu vytvoř událost pojmenovanou jako minulý fakt, například OrderPaid nebo OrderCancelled.
- Payload obsahuje event ID, order ID, verzi schématu, occurred_at a jen data potřebná příjemci. Nevkládej do něj serializovanou ORM entitu.
- Objednávku i událost zapiš v jedné transakci do outbox tabulky. Publisher potvrzené řádky následně odešle do fronty.
- Optimistický lock nebo unikátní business klíč zabrání dvěma souběžným požadavkům provést stejný přechod dvakrát.
BEGIN; UPDATE orders ...; INSERT INTO outbox ...; COMMIT; Oficiální PostgreSQL dokumentace k transakcím 3. Provozuj idempotentní workery
- Worker nejprve ověří event ID nebo business klíč. Opakované doručení vrátí úspěch bez druhého e-mailu, zásilky či faktury.
- Acknowledgement odešli až po potvrzeném lokálním zápisu. Dočasné chyby opakuj s exponenciálním odstupem a jitterem.
- Trvalé chyby po omezeném počtu pokusů přesuň do dead-letter queue s kontextem, ale bez tajných údajů.
- Výjimky zpřístupni operátorovi: může opravit vstup, bezpečně zopakovat krok a vidí úplnou auditní stopu.
php bin/console messenger:consume async --time-limit=3600 Oficiální Symfony Messenger dokumentace Krok 4
Simuluj duplicity i výpadky
Proces je spolehlivý teprve tehdy, když stejný výsledek vznikne po opakování, restartu i souběhu.
-
Pošli událost dvakrát
Worker provede vedlejší efekt jednou a druhé doručení označí jako již zpracované.
php bin/phpunit --filter OrderWorkflowIdempotency -
Ukonči worker po externím volání
Po restartu nezdvojí zásilku ani doklad; používá idempotency key externího systému nebo lokální mapování výsledku.
-
Vyvolej dvě změny současně
Jedna uspěje a druhá dostane čitelný konflikt. Historie i outbox odpovídají pouze potvrzenému přechodu.
Když to zlobí
Nejčastější chyby
Objednávka je paid, ale událost se neposlala
Datový zápis a publish nejsou atomické. Použij transactional outbox a samostatný opakovatelný publisher.
Zákazník dostal stejný e-mail dvakrát
Consumer předpokládá doručení právě jednou. Přidej idempotency key a perzistentní záznam dokončeného efektu.
Zpráva se opakuje bez konce
Rozliš dočasnou a trvalou chybu, omez retry a po vyčerpání pokusů ji přesuň do DLQ s alertem.
Stav mění controller i worker
Přesuň přechod do jednoho aplikačního use-casu a všechny vstupy veď přes něj.
Hotovo
Objednávka má řiditelné workflow.
Přechody jsou explicitní, události se neztratí a workery bezpečně zvládají opakované doručení i výpadky služeb.