Test Saga Compensation When Payment Succeeds but Inventory Times Out
Events and Invariants
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 | timeoutRefundRequested->InventoryReleased->Cancelled
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.
Simulator Design
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 state |
Property Tests
Property 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?
Comments
No comments yet. Start the discussion.