Created
February 19, 2024 14:38
-
-
Save jckw/10949a19ac74b896f65b27528ff3c43d to your computer and use it in GitHub Desktop.
A simple Saga implementation with TypeScript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Saga<TContext> { | |
private operations: Array<{ | |
up: (context: any) => Promise<any> | |
down: (context: any) => Promise<void> | |
}> = [] | |
add<TNewContext>( | |
up: (context: TContext) => Promise<TNewContext>, | |
down: (context: Partial<TContext & TNewContext>) => Promise<void> | |
): Saga<TContext & TNewContext> { | |
this.operations.push({ up, down }) | |
return this as unknown as Saga<TContext & TNewContext> | |
} | |
async execute(initialContext: Partial<TContext> = {}): Promise<void> { | |
const completed: Array<{ | |
down: (context: Partial<TContext>) => Promise<void> | |
}> = [] | |
let context = initialContext | |
try { | |
for (const { up, down } of this.operations) { | |
const result = await up(context) | |
context = { ...context, ...result } | |
completed.push({ down }) | |
} | |
} catch (error) { | |
console.error("Error encountered, rolling back...", error) | |
// Rollback in reverse order | |
for (const { down } of completed.reverse()) { | |
try { | |
await down(context) | |
} catch (rollbackError) { | |
console.error("Rollback failed", rollbackError) | |
// Handle rollback failure, potentially a manual intervention alert | |
} | |
} | |
// Rethrow or handle the original error as needed | |
throw error | |
} | |
} | |
} | |
// Usage example | |
const saga = new Saga() | |
saga | |
.add( | |
async () => { | |
console.log("Step 1") | |
return { step1: "done" } | |
}, | |
async () => { | |
console.log("Rollback step 1") | |
} | |
) | |
.add( | |
async (context) => { | |
console.log("Step 2", context.step1) | |
return { step2: "done" } | |
}, | |
async () => { | |
console.log("Rollback step 2") | |
} | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment