mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-06 04:22:53 +00:00
fix(agents): release session lock on manual abort
This commit is contained in:
44
src/agents/embedded-agent-runner/run/attempt-abort.test.ts
Normal file
44
src/agents/embedded-agent-runner/run/attempt-abort.test.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { releaseEmbeddedAttemptSessionLockForAbort } from "./attempt-abort.js";
|
||||
|
||||
describe("releaseEmbeddedAttemptSessionLockForAbort", () => {
|
||||
it("releases the retained session lock for manual aborts", async () => {
|
||||
const releaseHeldLockForAbort = vi.fn(async () => {});
|
||||
const warn = vi.fn();
|
||||
|
||||
releaseEmbeddedAttemptSessionLockForAbort({
|
||||
sessionLockController: { releaseHeldLockForAbort },
|
||||
log: { warn },
|
||||
runId: "run-manual",
|
||||
abortKind: "abort",
|
||||
});
|
||||
|
||||
await Promise.resolve();
|
||||
|
||||
expect(releaseHeldLockForAbort).toHaveBeenCalledTimes(1);
|
||||
expect(warn).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("logs release failures without throwing from the abort path", async () => {
|
||||
const releaseError = new Error("locked");
|
||||
const releaseHeldLockForAbort = vi.fn(async () => {
|
||||
throw releaseError;
|
||||
});
|
||||
const warn = vi.fn();
|
||||
|
||||
releaseEmbeddedAttemptSessionLockForAbort({
|
||||
sessionLockController: { releaseHeldLockForAbort },
|
||||
log: { warn },
|
||||
runId: "run-timeout",
|
||||
abortKind: "timeout abort",
|
||||
});
|
||||
|
||||
await Promise.resolve();
|
||||
await Promise.resolve();
|
||||
|
||||
expect(releaseHeldLockForAbort).toHaveBeenCalledTimes(1);
|
||||
expect(warn).toHaveBeenCalledWith(
|
||||
"failed to release session lock on timeout abort: runId=run-timeout Error: locked",
|
||||
);
|
||||
});
|
||||
});
|
||||
18
src/agents/embedded-agent-runner/run/attempt-abort.ts
Normal file
18
src/agents/embedded-agent-runner/run/attempt-abort.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import type { EmbeddedAttemptSessionLockController } from "./attempt.session-lock.js";
|
||||
|
||||
type AbortLockReleaseLog = {
|
||||
warn(message: string): void;
|
||||
};
|
||||
|
||||
export function releaseEmbeddedAttemptSessionLockForAbort(params: {
|
||||
sessionLockController: Pick<EmbeddedAttemptSessionLockController, "releaseHeldLockForAbort">;
|
||||
log: AbortLockReleaseLog;
|
||||
runId: string;
|
||||
abortKind: "abort" | "timeout abort";
|
||||
}): void {
|
||||
void params.sessionLockController.releaseHeldLockForAbort().catch((err) => {
|
||||
params.log.warn(
|
||||
`failed to release session lock on ${params.abortKind}: runId=${params.runId} ${String(err)}`,
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -308,6 +308,7 @@ import {
|
||||
rotateTranscriptAfterCompaction,
|
||||
shouldRotateCompactionTranscript,
|
||||
} from "../compaction-successor-transcript.js";
|
||||
import { releaseEmbeddedAttemptSessionLockForAbort } from "./attempt-abort.js";
|
||||
import { resolveAttemptWorkspaceBootstrapRouting } from "./attempt-bootstrap-routing.js";
|
||||
import { configureEmbeddedAttemptHttpRuntime } from "./attempt-http-runtime.js";
|
||||
import {
|
||||
@@ -2984,12 +2985,13 @@ export async function runEmbeddedAttempt(
|
||||
sessionFile: params.sessionFile,
|
||||
reason: "timeout",
|
||||
});
|
||||
void sessionLockController.releaseHeldLockForAbort().catch((err) => {
|
||||
log.warn(
|
||||
`failed to release session lock on timeout abort: runId=${params.runId} ${String(err)}`,
|
||||
);
|
||||
});
|
||||
}
|
||||
releaseEmbeddedAttemptSessionLockForAbort({
|
||||
sessionLockController,
|
||||
log,
|
||||
runId: params.runId,
|
||||
abortKind: isTimeout ? "timeout abort" : "abort",
|
||||
});
|
||||
};
|
||||
abortRunForExternalSignal = abortRun;
|
||||
const idleTimeoutTrigger: ((error: Error) => void) | undefined = (error) => {
|
||||
|
||||
Reference in New Issue
Block a user