ARCHIVED from builddistributedsystem.com on 2026-04-28 — URL: https://builddistributedsystem.com/tracks/reactor/tasks/task-27-1-5-event-compensation
TASK

Implementation

Distributed transactions across multiple services cannot use a single database commit. A saga breaks the operation into a sequence of local steps, each with a corresponding compensation action. If any step fails, all already-completed steps are rolled back by executing their compensations in reverse order.

Implement a node that executes sagas and handles failures:

// Execute all steps successfully
{ "type": "execute", "msg_id": 1,
  "saga_id": "booking-123",
  "steps": ["book_flight", "book_hotel", "book_car"] }
-> { "type": "saga_completed", "in_reply_to": 1,
    "saga_id": "booking-123",
    "state": "completed", "completed_steps": 3 }

// Fail at book_hotel, compensate completed steps in reverse
{ "type": "execute", "msg_id": 2,
  "saga_id": "booking-124",
  "steps": ["book_flight", "book_hotel"],
  "fail_step": "book_hotel" }
-> { "type": "saga_compensated", "in_reply_to": 2,
    "saga_id": "booking-124",
    "state": "compensated",
    "compensated_steps": ["book_flight"] }

When a step fails, only the steps that were successfully completed before it need to be compensated — the failing step itself is not compensated because it never completed. Compensation order is the reverse of execution order.

Sample Test Cases

Execute saga successfullyTimeout: 5000ms
Input
{
  "src": "orchestrator",
  "dest": "saga",
  "body": {
    "type": "execute",
    "msg_id": 1,
    "saga_id": "booking-123",
    "steps": [
      "book_flight",
      "book_hotel",
      "book_car"
    ]
  }
}
Expected Output
{"type": "saga_completed", "in_reply_to": 1, "saga_id": "booking-123", "state": "completed", "completed_steps": 3}
Compensate on failureTimeout: 5000ms
Input
{
  "src": "orchestrator",
  "dest": "saga",
  "body": {
    "type": "execute",
    "msg_id": 1,
    "saga_id": "booking-124",
    "steps": [
      "book_flight",
      "book_hotel"
    ],
    "fail_step": "book_hotel"
  }
}
Expected Output
{"type": "saga_compensated", "in_reply_to": 1, "saga_id": "booking-124", "state": "compensated", "compensated_steps": ["book_flight"]}

Hints

Hint 1
Execute steps in order; on any failure, compensate all previously completed steps in reverse order
Hint 2
fail_step in the test input tells you which step should fail — simulate that failure
Hint 3
compensated_steps must list only the steps that were successfully executed before the failure
Hint 4
The compensation order is reverse of execution: last completed step is compensated first
Hint 5
saga_id must be echoed back in every response so the caller can correlate requests
OVERVIEW

Theoretical Hub

Concept overview coming soon

Key Concepts

saga patterndistributed transactionscompensationrollbackchoreography
main.py
python
Implement Event Compensation and Sagas - The Reactor | Build Distributed Systems