TASK
Implementation
Sagas: sequence of local transactions with compensations. On failure, compensate in reverse order.
Sample Test Cases
Execute all steps in sequenceTimeout: 5000ms
Input
{"src":"c0","dest":"n1","body":{"type":"init","msg_id":1,"node_id":"n1","node_ids":["n1"]}}
{"src":"c1","dest":"n1","body":{"type":"saga_execute","msg_id":2,"saga_id":"saga1","steps":[{"name":"reserve_inventory","action":"reserve","compensation":"release"},{"name":"charge_payment","action":"charge","compensation":"refund"},{"name":"ship_order","action":"ship","compensation":"cancel_shipment"}]}}
Expected Output
{"src":"n1","dest":"c0","body":{"type":"init_ok","in_reply_to":1,"msg_id":0}}
{"src":"n1","dest":"c1","body":{"type":"saga_execute_ok","in_reply_to":2,"msg_id":1,"saga_id":"saga1","status":"completed","steps_executed":["reserve_inventory","charge_payment","ship_order"]}}
Hints
Hint 1▾
Each step has compensating action
Hint 2▾
On failure, run compensations in reverse
Hint 3▾
Eventual consistency
OVERVIEW
Theoretical Hub
Sagas
Sagas break transactions into local steps with compensations. No locks held. Eventually consistent.
Key Concepts
sagacompensationeventual consistency
main.py
python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/usr/bin/env python3
class SagaStep:
def __init__(self, name, action, compensation):
self.name = name
self.action = action
self.compensation = compensation
class SagaOrchestrator:
def execute(self, steps, context):
completed = []
for step in steps:
try:
step.action(context)
completed.append(step)
except:
for s in reversed(completed):
s.compensation(context)
return 'compensated'
return 'completed'