mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-28 18:38:13 +00:00
75 lines
2.5 KiB
TypeScript
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"]);
|
|
});
|
|
});
|