An order reserves inventory, charges payment, then times out waiting for reservation confirmation. Cancellation begins. A late inventory success arrives after the refund. Without a state model, stock remains held or payment is refunded twice.
Define events and invariants
OrderCreated -> InventoryReserved -> PaymentCharged -> Confirmed
| timeout
v
RefundRequested -> InventoryReleased -> Cancelled
Enter fullscreen mode Exit fullscreen mode
invariant 1: terminal Confirmed implies one charge and one reservation
invariant 2: terminal Cancelled implies no net charge and no reservation
invariant 3: each compensation key produces at most one external effect
Enter fullscreen mode Exit fullscreen mode
Build an in-memory simulator that permutes duplicate delivery, timeout, late success, refund failure, and process restart. Persist event IDs and state revisions; reject transitions from stale revisions.
Injection Expected terminal evidence payment succeeds, reserve response lost reconcile before refund refund delivered twice one provider effect late reserve after cancel release command emitted compensation fails nonterminal alertable stateProperty tests should generate event orders and assert invariants after quiescence. Keep a minimal failing sequence whenever one breaks. Do not claim exactly-once delivery; make effects idempotent and reconciliation repeatable.
This simulator does not reproduce production brokers, provider semantics, or network timing. It validates a protocol hypothesis. Which compensation in your current Saga has no durable idempotency key?
답글 남기기