Spaces:
Sleeping
Sleeping
| // File: tasks/saga/source.js | |
| // Express.js payment saga source bundle. | |
| const TRANSITIONS = { | |
| "Idle:Reserve": "Reserved", | |
| "Reserved:Authorize": "Authorized", | |
| "Authorized:Capture": "Captured", | |
| "Captured:Settle": "Settled", | |
| "Reserved:CompensateReserve": "Compensated", | |
| "Authorized:CompensateAuthorize": "Compensating", | |
| "Compensating:CompensateReserve": "Compensated", | |
| "Captured:CompensateCapture": "Compensating", | |
| }; | |
| function transition(state, event) { | |
| if (event === "Fail") { | |
| return "Failed"; | |
| } | |
| return TRANSITIONS[`${state}:${event}`] ?? state; | |
| } | |
| function runSaga(events) { | |
| return events.reduce(transition, "Idle"); | |
| } | |
| function isCharged(state) { | |
| return state === "Captured" || state === "Settled"; | |
| } | |
| const HAPPY_PATH = ["Reserve", "Authorize", "Capture", "Settle"]; | |
| const express = require("express"); | |
| const app = express(); | |
| app.use(express.json()); | |
| const sagaStore = {}; | |
| app.post("/saga/start", (request, response) => { | |
| const sagaId = `saga_${Date.now()}`; | |
| sagaStore[sagaId] = { state: "Idle", history: [] }; | |
| response.json({ sagaId, state: "Idle" }); | |
| }); | |
| app.post("/saga/:sagaId/event", (request, response) => { | |
| const { sagaId } = request.params; | |
| const { event } = request.body; | |
| if (!sagaStore[sagaId]) { | |
| return response.status(404).json({ error: "Not found" }); | |
| } | |
| const saga = sagaStore[sagaId]; | |
| const nextState = transition(saga.state, event); | |
| saga.history.push({ from: saga.state, event, to: nextState }); | |
| saga.state = nextState; | |
| response.json({ sagaId, state: nextState, charged: isCharged(nextState) }); | |
| }); | |
| app.get("/saga/:sagaId", (request, response) => { | |
| const saga = sagaStore[request.params.sagaId]; | |
| if (!saga) { | |
| return response.status(404).json({ error: "Not found" }); | |
| } | |
| response.json({ state: saga.state, history: saga.history }); | |
| }); |