UNPKG

@sema-agent/core

Version:

Stateless, task-oriented AI agent core

31 lines (30 loc) • 1.42 kB
import { settleTeardownLeg } from "./teardown-bounded.js"; export function createRollbackStack(report) { const cleanups = []; let state = "armed"; return { push(cleanup) { if (state !== "armed") { throw new Error(`RollbackStack.push after ${state}: a cleanup registered once prepare has ${state === "committed" ? "succeeded" : "started unwinding"} would ${state === "committed" ? "never be owned by the failure path" : "never run"} — acquire resources only while the stack is armed.`); } cleanups.push(cleanup); }, commit() { if (state !== "armed") throw new Error(`RollbackStack.commit after ${state}: commit is the success path's one disarm and cannot follow an unwind or a second commit.`); state = "committed"; cleanups.length = 0; }, async unwindAll() { if (state !== "armed") return; state = "unwinding"; const total = cleanups.length; let leg = total; for (let cleanup = cleanups.pop(); cleanup !== undefined; cleanup = cleanups.pop(), leg--) { await settleTeardownLeg(cleanup, `${cleanup.name !== "" ? cleanup.name : "anonymous cleanup"} (rollback leg ${leg} of ${total}, prepare-throw)`, report); } state = "unwound"; }, }; }