DEV Community

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 | timeout
  • RefundRequested -> 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.