Saga — sequence of local transactions with compensation.
1class Saga {2 constructor() {3 this.steps = [];4 }56 addStep(execute, compensate) {7 this.steps.push({ execute, compensate });8 return this;9 }1011 async run(context) {12 const completedSteps = [];1314 try {15 for (const step of this.steps) {16 const result = await step.execute(context);17 context = { ...context, ...result };18 completedSteps.push(step);19 }20 return { success: true, context };21 } catch (err) {22 // Compensate in reverse order23 for (const step of completedSteps.reverse()) {24 try {25 await step.compensate(context);26 } catch (compErr) {27 console.error("Compensation failed:", compErr);28 }29 }30 return { success: false, error: err };31 }32 }33}3435// Order saga36const orderSaga = new Saga()37 .addStep(38 async (ctx) => {39 const order = await createOrder(ctx);40 return { orderId: order.id };41 },42 async (ctx) => await cancelOrder(ctx.orderId)43 )44 .addStep(45 async (ctx) => {46 await chargePayment(ctx.orderId, ctx.amount);47 return {};48 },49 async (ctx) => await refundPayment(ctx.orderId)50 )51 .addStep(52 async (ctx) => {53 await reserveInventory(ctx.items);54 return {};55 },56 async (ctx) => await releaseInventory(ctx.items)57 );5859const result = await orderSaga.run({60 userId: "user-123",61 items: ["item1", "item2"],62 amount: 99.99,63});