Skip to main content

Transactional outbox and duplicate-effect contracts

This required 24–36-hour package supplies guided Lab 3's implementation core: lessons and predictions 6–8, implementation/failure experiments 12–20, assessment/repair 6–8. Reuse evidence rather than implement two outboxes. The original isolation anomaly harness, WAL/checkpoint model and saga review remain required. Estimates await learner pilots; see the reconciled semester workload.

Prerequisite bridge​

Module 1 established local transaction boundaries. Module 2 separated replayability from safe publication; Module 3 separated receipt from visibility. Now connect two distinct databases through an explicitly duplicate-prone relay. No single SQL transaction spans producer, broker and consumer.

Learning sequence​

  1. Atomic intent and lost replies.
  2. Delivery duplicates and inbox effects.
  3. Retention, ordering and external effects.
  4. Prediction practice, runnable implementation and all TX1–TX6 gates.

Download outbox-contracts.zip. Requires Python 3 with standard-library SQLite. Read the README, implement starter.py, and run python3 -B check.py starter. Reference is calibration after attempting independently.

Executable contract​

Producer inserts an order and an outbox event in one local transaction. A single relay appends to an abstract broker list, then marks the event sent. Consumer inserts an inbox marker and increments a local balance in another transaction. Identical event ID/payload is a retry; conflicting payload under the same ID is rejected. The lab retains inbox and outbox rows indefinitely and assumes globally unique IDs within this experiment.

Injected exceptions occur before and after each critical local commit and publication boundary. The checker covers 27 combined producer/relay/consumer failure paths, 243 repeated/reordered delivery sequences, conflicts, caller-transaction ownership and ordinary file reopening. The reference does not implement network I/O, broker persistence, concurrent relays, process kills or power-loss tests. A retained Python list stands for acknowledged messages across relay retries, not a production broker.

Evidence and completion​

Keep a failure ledger with cut, producer rows, broker entries, consumer rows, balance, retry and final state. Preserve at least one duplicate publish with one resulting balance increment. State the liveness assumptions: delivery and retry must eventually succeed; permanent failure leaves work pending. Complete the original isolation and saga labs separately, and do not claim exactly-once email/payment effects from a database inbox test.