mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-09 18:14:31 +00:00
fix(heartbeat): scope exec wake dispatch to session key (#32724)
Merged via squash.
Prepared head SHA: 563fee0e65
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
This commit is contained in:
@@ -1,5 +1,9 @@
|
||||
import path from "node:path";
|
||||
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import {
|
||||
resetHeartbeatWakeStateForTests,
|
||||
setHeartbeatWakeHandler,
|
||||
} from "../infra/heartbeat-wake.js";
|
||||
import { applyPathPrepend, findPathKey } from "../infra/path-prepend.js";
|
||||
import { peekSystemEvents, resetSystemEventsForTest } from "../infra/system-events.js";
|
||||
import { captureEnv } from "../test-utils/env.js";
|
||||
@@ -510,6 +514,14 @@ describe("exec exit codes", () => {
|
||||
});
|
||||
|
||||
describe("exec notifyOnExit", () => {
|
||||
beforeEach(() => {
|
||||
resetHeartbeatWakeStateForTests();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
resetHeartbeatWakeStateForTests();
|
||||
});
|
||||
|
||||
it("enqueues a system event when a backgrounded exec exits", async () => {
|
||||
const tool = createNotifyOnExitExecTool();
|
||||
|
||||
@@ -521,6 +533,45 @@ describe("exec notifyOnExit", () => {
|
||||
expect(hasEvent).toBe(true);
|
||||
});
|
||||
|
||||
it("scopes notifyOnExit heartbeat wake to the exec session key", async () => {
|
||||
const tool = createNotifyOnExitExecTool();
|
||||
const wakeHandler = vi.fn().mockResolvedValue({ status: "skipped", reason: "disabled" });
|
||||
const dispose = setHeartbeatWakeHandler(
|
||||
wakeHandler as unknown as Parameters<typeof setHeartbeatWakeHandler>[0],
|
||||
);
|
||||
try {
|
||||
const sessionId = await startBackgroundCommand(tool, echoAfterDelay("notify"));
|
||||
|
||||
await expect
|
||||
.poll(() => wakeHandler.mock.calls[0]?.[0], NOTIFY_POLL_OPTIONS)
|
||||
.toMatchObject({
|
||||
reason: `exec:${sessionId}:exit`,
|
||||
sessionKey: DEFAULT_NOTIFY_SESSION_KEY,
|
||||
});
|
||||
} finally {
|
||||
dispose();
|
||||
}
|
||||
});
|
||||
|
||||
it("keeps notifyOnExit heartbeat wake unscoped for non-agent session keys", async () => {
|
||||
const tool = createNotifyOnExitExecTool({ sessionKey: "global" });
|
||||
const wakeHandler = vi.fn().mockResolvedValue({ status: "skipped", reason: "disabled" });
|
||||
const dispose = setHeartbeatWakeHandler(
|
||||
wakeHandler as unknown as Parameters<typeof setHeartbeatWakeHandler>[0],
|
||||
);
|
||||
try {
|
||||
const sessionId = await startBackgroundCommand(tool, echoAfterDelay("notify"));
|
||||
|
||||
await expect
|
||||
.poll(() => wakeHandler.mock.calls[0]?.[0], NOTIFY_POLL_OPTIONS)
|
||||
.toEqual({
|
||||
reason: `exec:${sessionId}:exit`,
|
||||
});
|
||||
} finally {
|
||||
dispose();
|
||||
}
|
||||
});
|
||||
|
||||
it.each<NotifyNoopCase>(NOOP_NOTIFY_CASES)("$label", runNotifyNoopCase);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user