mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-29 23:58:40 +00:00
fix: release sqlite locks on sync errors
This commit is contained in:
@@ -458,6 +458,38 @@ describe("SQLite session transcript store", () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it("preserves an explicit transcript database path when listing by agent", () => {
|
||||
const stateDir = createTempDir();
|
||||
const env = { OPENCLAW_STATE_DIR: stateDir };
|
||||
const customPath = path.join(stateDir, "custom-agent.sqlite");
|
||||
|
||||
appendSqliteSessionTranscriptEvent({
|
||||
env,
|
||||
path: customPath,
|
||||
agentId: "worker-1",
|
||||
sessionId: "session-1",
|
||||
event: { type: "message", id: "m1" },
|
||||
now: () => 100,
|
||||
});
|
||||
|
||||
const [scope] = listSqliteSessionTranscripts({
|
||||
env,
|
||||
path: customPath,
|
||||
agentId: "worker-1",
|
||||
});
|
||||
|
||||
expect(scope).toEqual({
|
||||
agentId: "worker-1",
|
||||
path: customPath,
|
||||
sessionId: "session-1",
|
||||
updatedAt: 100,
|
||||
eventCount: 1,
|
||||
});
|
||||
expect(
|
||||
scope ? loadSqliteSessionTranscriptEvents(scope).map((entry) => entry.event) : [],
|
||||
).toEqual([{ type: "message", id: "m1" }]);
|
||||
});
|
||||
|
||||
it("deletes transcript snapshots with the transcript", () => {
|
||||
const stateDir = createTempDir();
|
||||
const env = { OPENCLAW_STATE_DIR: stateDir };
|
||||
|
||||
@@ -479,7 +479,7 @@ export function listSqliteSessionTranscripts(
|
||||
? [
|
||||
{
|
||||
agentId: normalizeAgentId(options.agentId),
|
||||
path: undefined,
|
||||
path: options.path,
|
||||
},
|
||||
]
|
||||
: listOpenClawRegisteredAgentDatabases(options);
|
||||
|
||||
@@ -117,6 +117,23 @@ describe("withOpenClawStateLock", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("releases the lease when the guarded task throws synchronously", async () => {
|
||||
await withTempDir({ prefix: "openclaw-state-lock-sync-throw-" }, async (dir) => {
|
||||
const dbPath = path.join(dir, "state.sqlite");
|
||||
expect.assertions(2);
|
||||
|
||||
await expect(
|
||||
withOpenClawStateLock("shared", { path: dbPath, retries: FAST_RETRY }, () => {
|
||||
throw new Error("boom");
|
||||
}),
|
||||
).rejects.toThrow("boom");
|
||||
|
||||
await expect(
|
||||
withOpenClawStateLock("shared", { path: dbPath, retries: FAST_RETRY }, async () => "ok"),
|
||||
).resolves.toBe("ok");
|
||||
});
|
||||
});
|
||||
|
||||
it("rejects and aborts the guarded task when lease renewal loses ownership", async () => {
|
||||
await withTempDir({ prefix: "openclaw-state-lock-lost-" }, async (dir) => {
|
||||
const dbPath = path.join(dir, "state.sqlite");
|
||||
@@ -135,16 +152,19 @@ describe("withOpenClawStateLock", () => {
|
||||
});
|
||||
await entered;
|
||||
|
||||
runOpenClawStateWriteTransaction((database) => {
|
||||
const db = getNodeSqliteKysely<StateLockTestDatabase>(database.db);
|
||||
executeSqliteQuerySync(
|
||||
database.db,
|
||||
db
|
||||
.deleteFrom("state_leases")
|
||||
.where("scope", "=", "runtime.lock")
|
||||
.where("lease_key", "=", "shared"),
|
||||
);
|
||||
}, { path: dbPath });
|
||||
runOpenClawStateWriteTransaction(
|
||||
(database) => {
|
||||
const db = getNodeSqliteKysely<StateLockTestDatabase>(database.db);
|
||||
executeSqliteQuerySync(
|
||||
database.db,
|
||||
db
|
||||
.deleteFrom("state_leases")
|
||||
.where("scope", "=", "runtime.lock")
|
||||
.where("lease_key", "=", "shared"),
|
||||
);
|
||||
},
|
||||
{ path: dbPath },
|
||||
);
|
||||
|
||||
await expect(locked).rejects.toThrow("Lost SQLite state lock runtime.lock:shared");
|
||||
expect(signal.aborted).toBe(true);
|
||||
|
||||
@@ -277,9 +277,9 @@ export async function withOpenClawStateLock<T>(
|
||||
}
|
||||
}, renewEveryMs);
|
||||
renewal.unref?.();
|
||||
const taskPromise = task(abortController.signal);
|
||||
void taskPromise.catch(() => {});
|
||||
try {
|
||||
const taskPromise = Promise.resolve(task(abortController.signal));
|
||||
void taskPromise.catch(() => {});
|
||||
return await Promise.race([taskPromise, lostLock]);
|
||||
} finally {
|
||||
clearInterval(renewal);
|
||||
|
||||
Reference in New Issue
Block a user