3 changed files with 111 additions and 50 deletions
@ -0,0 +1,29 @@ |
|||
type TransitionAction = () => Promise<void> | void; |
|||
|
|||
export interface TransitionTransactionConfig { |
|||
prepare?: TransitionAction; |
|||
commit: TransitionAction; |
|||
rollback: TransitionAction; |
|||
} |
|||
|
|||
export class TransitionTransaction { |
|||
private readonly prepare: TransitionAction; |
|||
private readonly commit: TransitionAction; |
|||
private readonly rollback: TransitionAction; |
|||
|
|||
constructor(config: TransitionTransactionConfig) { |
|||
this.prepare = config.prepare ?? (() => {}); |
|||
this.commit = config.commit; |
|||
this.rollback = config.rollback; |
|||
} |
|||
|
|||
async execute(): Promise<void> { |
|||
try { |
|||
await this.prepare(); |
|||
await this.commit(); |
|||
} catch (error) { |
|||
await this.rollback(); |
|||
throw error; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,24 @@ |
|||
import { describe, expect, it, vi } from "vitest"; |
|||
import { TransitionTransaction } from "@/scene/TransitionTransaction"; |
|||
|
|||
describe("TransitionTransaction", () => { |
|||
it("rolls back when prepare fails and never commits", async () => { |
|||
const prepareError = new Error("prepare failed"); |
|||
const prepare = vi.fn(async () => { |
|||
throw prepareError; |
|||
}); |
|||
const commit = vi.fn(async () => {}); |
|||
const rollback = vi.fn(async () => {}); |
|||
|
|||
const transaction = new TransitionTransaction({ |
|||
prepare, |
|||
commit, |
|||
rollback, |
|||
}); |
|||
|
|||
await expect(transaction.execute()).rejects.toThrowError("prepare failed"); |
|||
expect(prepare).toHaveBeenCalledTimes(1); |
|||
expect(rollback).toHaveBeenCalledTimes(1); |
|||
expect(commit).not.toHaveBeenCalled(); |
|||
}); |
|||
}); |
|||
Loading…
Reference in new issue