Files
openclaw/src/infra/sqlite-transaction.test.ts
Peter Steinberger 8604da8e16 Reapply "refactor: move runtime state to SQLite"
This reverts commit 694ca50e97.
2026-05-27 13:27:43 +01:00

75 lines
2.5 KiB
TypeScript

import { afterEach, describe, expect, it } from "vitest";
import { requireNodeSqlite } from "./node-sqlite.js";
import { runSqliteImmediateTransactionSync } from "./sqlite-transaction.js";
const openDatabases: Array<import("node:sqlite").DatabaseSync> = [];
function createDatabase(): import("node:sqlite").DatabaseSync {
const { DatabaseSync } = requireNodeSqlite();
const db = new DatabaseSync(":memory:");
db.exec("CREATE TABLE entries (id TEXT NOT NULL PRIMARY KEY, value TEXT NOT NULL);");
openDatabases.push(db);
return db;
}
function readEntries(db: import("node:sqlite").DatabaseSync): string[] {
return db
.prepare("SELECT id FROM entries ORDER BY id")
.all()
.map((row) => (row as { id: string }).id);
}
afterEach(() => {
for (const db of openDatabases.splice(0)) {
db.close();
}
});
describe("runSqliteImmediateTransactionSync", () => {
it("keeps outer writes when a nested savepoint rolls back", () => {
const db = createDatabase();
runSqliteImmediateTransactionSync(db, () => {
db.prepare("INSERT INTO entries(id, value) VALUES (?, ?)").run("outer", "kept");
expect(() =>
runSqliteImmediateTransactionSync(db, () => {
db.prepare("INSERT INTO entries(id, value) VALUES (?, ?)").run("inner", "rolled back");
throw new Error("nested failure");
}),
).toThrow("nested failure");
});
expect(readEntries(db)).toEqual(["outer"]);
});
it("commits nested savepoint writes with the outer transaction", () => {
const db = createDatabase();
runSqliteImmediateTransactionSync(db, () => {
db.prepare("INSERT INTO entries(id, value) VALUES (?, ?)").run("outer", "kept");
runSqliteImmediateTransactionSync(db, () => {
db.prepare("INSERT INTO entries(id, value) VALUES (?, ?)").run("inner", "kept");
});
});
expect(readEntries(db)).toEqual(["inner", "outer"]);
});
it("rejects Promise-returning operations and rolls back their synchronous writes", () => {
const db = createDatabase();
expect(() =>
runSqliteImmediateTransactionSync(db, async () => {
db.prepare("INSERT INTO entries(id, value) VALUES (?, ?)").run("async", "rolled back");
return "done";
}),
).toThrow("must be synchronous");
expect(readEntries(db)).toEqual([]);
runSqliteImmediateTransactionSync(db, () => {
db.prepare("INSERT INTO entries(id, value) VALUES (?, ?)").run("after", "works");
});
expect(readEntries(db)).toEqual(["after"]);
});
});