Saga-pattern rollback utility for Cloudflare Workflows
npm install cf-workflow-rollbackSaga-pattern rollback utility for Cloudflare Workflows.
``bash`
npm install cf-workflow-rollbackor
bun add cf-workflow-rollback
`typescript
import { WorkflowEntrypoint, type WorkflowEvent, type WorkflowStep } from "cloudflare:workers";
import { withRollback } from "cf-workflow-rollback";
export class MyWorkflow extends WorkflowEntrypoint
async run(event: WorkflowEvent
const step = withRollback(workflowStep);
try {
// Regular step (no rollback needed)
const data = await step.do("fetch data", async () => {
return fetchExternalData();
});
// Step with rollback - if a later step fails, this will be undone
const id = await step.doWithRollback("save to database", {
run: async () => {
return await db.insert(data);
},
undo: async (error, id) => {
await db.delete(id);
},
});
// Another step with rollback
await step.doWithRollback("charge payment", {
run: async () => {
return await payments.charge(event.payload.amount);
},
undo: async (error, chargeId) => {
await payments.refund(chargeId);
},
});
// Final step (no rollback - if this fails, previous steps are undone)
await step.do("send confirmation", async () => {
await sendEmail(event.payload.email);
});
} catch (error) {
// Rollback all successful steps in reverse order
await step.rollbackAll(error);
// Optionally: cleanup steps that always run on failure
await step.do("notify failure", async () => {
await sendFailureNotification();
});
throw error;
}
}
}
`
Wraps a Cloudflare Workflow step with rollback capabilities.
Returns an object with:
| Method | Description |
|--------|-------------|
| do(name, callback) | The original step.do method |do(name, config, callback)
| | The original step.do method with config |doWithRollback(name, handler, config?)
| | Execute a step with an undo handler |rollbackAll(error)
| | Execute all registered undo handlers in LIFO order |
`typescript`
type RollbackHandler
run: () => Promise
undo: (err: unknown, value: T) => Promise
};
- run - The step function to executeundo
- - Called with the error and the return value of run if a later step fails
This utility implements the Saga pattern for Cloudflare Workflows:
1. Each doWithRollback step registers an undo handler after successful executionrollbackAll
2. Undo handlers are stored in a LIFO (last-in-first-out) stack
3. On failure, executes undo handlers in reverse orderstep.do
4. Each undo operation is wrapped in for durability and retry
The undo stack is correctly rebuilt on workflow replay because:
- step.do` returns cached results for completed steps
- Undo handlers are registered after each successful step
- The same sequence of steps produces the same undo stack
MIT