mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-18 21:34:46 +00:00
fix(clawsweeper): address review for automerge-openclaw-openclaw-82891 (2)
This commit is contained in:
@@ -78,6 +78,46 @@ describe("embedded attempt session lock lifecycle", () => {
|
||||
expect(events).toEqual(["prep-release", "post-write", "post-release"]);
|
||||
});
|
||||
|
||||
it("reuses its active post-prompt lock for nested session writes", async () => {
|
||||
const events: string[] = [];
|
||||
const sessionFile = await createTempSessionFile();
|
||||
const acquireSessionWriteLock = vi
|
||||
.fn()
|
||||
.mockResolvedValueOnce({ release: vi.fn(async () => events.push("prep-release")) })
|
||||
.mockResolvedValueOnce({ release: vi.fn(async () => events.push("post-release")) })
|
||||
.mockRejectedValueOnce(
|
||||
new SessionWriteLockTimeoutError({
|
||||
timeoutMs: lockOptions.timeoutMs,
|
||||
owner: "pid=789",
|
||||
lockPath: `${sessionFile}.lock`,
|
||||
}),
|
||||
);
|
||||
|
||||
const controller = await createEmbeddedAttemptSessionLockController({
|
||||
acquireSessionWriteLock,
|
||||
lockOptions: { ...lockOptions, sessionFile },
|
||||
});
|
||||
|
||||
await controller.releaseForPrompt();
|
||||
await controller.withSessionWriteLock(async () => {
|
||||
events.push("outer-start");
|
||||
await fs.appendFile(sessionFile, '{"type":"message","id":"local"}\n', "utf8");
|
||||
await controller.withSessionWriteLock(async () => {
|
||||
events.push("inner-write");
|
||||
});
|
||||
events.push("outer-end");
|
||||
});
|
||||
|
||||
expect(acquireSessionWriteLock).toHaveBeenCalledTimes(2);
|
||||
expect(events).toEqual([
|
||||
"prep-release",
|
||||
"outer-start",
|
||||
"inner-write",
|
||||
"outer-end",
|
||||
"post-release",
|
||||
]);
|
||||
});
|
||||
|
||||
it("drains queued Pi session events before reacquiring for cleanup", async () => {
|
||||
const events: string[] = [];
|
||||
let resolveQueue!: () => void;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { AsyncLocalStorage } from "node:async_hooks";
|
||||
import fs from "node:fs/promises";
|
||||
import { isSessionWriteLockTimeoutError } from "../../session-write-lock-error.js";
|
||||
import type { acquireSessionWriteLock } from "../../session-write-lock.js";
|
||||
@@ -257,6 +258,7 @@ export async function createEmbeddedAttemptSessionLockController(params: {
|
||||
});
|
||||
|
||||
let heldLock: SessionLock | undefined = await acquireLock();
|
||||
const activeWriteLock = new AsyncLocalStorage<SessionLock>();
|
||||
let fenceFingerprint: SessionFileFingerprint | undefined;
|
||||
let fenceActive = false;
|
||||
let takeoverDetected = false;
|
||||
@@ -310,12 +312,21 @@ export async function createEmbeddedAttemptSessionLockController(params: {
|
||||
if (takeoverDetected) {
|
||||
throw new EmbeddedAttemptSessionTakeoverError(params.lockOptions.sessionFile);
|
||||
}
|
||||
if (activeWriteLock.getStore()) {
|
||||
return await run();
|
||||
}
|
||||
const { lock, owned } = await acquireWriteLock();
|
||||
try {
|
||||
await assertSessionFileFence();
|
||||
const result = await run();
|
||||
await refreshSessionFileFence();
|
||||
return result;
|
||||
const runWithLock = async () => {
|
||||
const result = await run();
|
||||
await refreshSessionFileFence();
|
||||
return result;
|
||||
};
|
||||
if (owned) {
|
||||
return await activeWriteLock.run(lock, runWithLock);
|
||||
}
|
||||
return await runWithLock();
|
||||
} finally {
|
||||
if (owned) {
|
||||
await lock.release();
|
||||
|
||||
Reference in New Issue
Block a user