mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-04 03:34:04 +00:00
fix(gateway): bound maintenance run expiry checks
This commit is contained in:
@@ -394,6 +394,52 @@ describe("startGatewayMaintenanceTimers", () => {
|
||||
stopMaintenanceTimers(timers);
|
||||
});
|
||||
|
||||
it("evicts pending accepted agent dedupe entries with invalid run expiry", async () => {
|
||||
vi.useFakeTimers();
|
||||
vi.setSystemTime(new Date("2026-03-22T00:00:00Z"));
|
||||
const { startGatewayMaintenanceTimers } = await import("./server-maintenance.js");
|
||||
const deps = createMaintenanceTimerDeps();
|
||||
const now = Date.now();
|
||||
deps.dedupe.set("agent:invalid-expiry-pending-agent", {
|
||||
ts: now - DEDUPE_TTL_MS - 1,
|
||||
ok: true,
|
||||
payload: {
|
||||
runId: "invalid-expiry-pending-agent",
|
||||
sessionKey: "agent:main:main",
|
||||
status: "accepted",
|
||||
expiresAtMs: Number.POSITIVE_INFINITY,
|
||||
},
|
||||
});
|
||||
|
||||
const timers = startGatewayMaintenanceTimers(deps);
|
||||
|
||||
await vi.advanceTimersByTimeAsync(60_000);
|
||||
|
||||
expect(deps.dedupe.has("agent:invalid-expiry-pending-agent")).toBe(false);
|
||||
|
||||
stopMaintenanceTimers(timers);
|
||||
});
|
||||
|
||||
it("aborts active runs with invalid expiry timestamps", async () => {
|
||||
vi.useFakeTimers();
|
||||
vi.setSystemTime(new Date("2026-03-22T00:00:00Z"));
|
||||
const { startGatewayMaintenanceTimers } = await import("./server-maintenance.js");
|
||||
const deps = createMaintenanceTimerDeps();
|
||||
const runId = "run-invalid-expiry";
|
||||
const activeRun = createActiveRun("main");
|
||||
activeRun.expiresAtMs = Number.POSITIVE_INFINITY;
|
||||
deps.chatAbortControllers.set(runId, activeRun);
|
||||
|
||||
const timers = startGatewayMaintenanceTimers(deps);
|
||||
|
||||
await vi.advanceTimersByTimeAsync(60_000);
|
||||
|
||||
expect(activeRun.controller.signal.aborted).toBe(true);
|
||||
expect(deps.chatAbortControllers.has(runId)).toBe(false);
|
||||
|
||||
stopMaintenanceTimers(timers);
|
||||
});
|
||||
|
||||
it("keeps active exec approval dedupe aliases past the normal ttl", async () => {
|
||||
vi.useFakeTimers();
|
||||
vi.setSystemTime(new Date("2026-03-22T00:00:00Z"));
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { HealthSummary } from "../commands/health.js";
|
||||
import { sweepStaleRunContexts } from "../infra/agent-events.js";
|
||||
import { cleanOldMedia } from "../media/store.js";
|
||||
import { isFutureDateTimestampMs } from "../shared/number-coercion.js";
|
||||
import { abortChatRunById, type ChatAbortControllerEntry } from "./chat-abort.js";
|
||||
import { pruneStaleControlPlaneBuckets } from "./control-plane-rate-limit.js";
|
||||
import type { ChatRunState } from "./server-chat-state.js";
|
||||
@@ -124,7 +125,7 @@ export function startGatewayMaintenanceTimers(params: {
|
||||
return false;
|
||||
}
|
||||
const expiresAtMs = (payload as { expiresAtMs?: unknown }).expiresAtMs;
|
||||
return typeof expiresAtMs === "number" && Number.isFinite(expiresAtMs) && expiresAtMs > now;
|
||||
return isFutureDateTimestampMs(expiresAtMs, { nowMs: now });
|
||||
};
|
||||
const isActiveRunDedupeKey = (key: string, dedupeEntry: DedupeEntry) => {
|
||||
if (!key.startsWith("agent:") && !key.startsWith("chat:")) {
|
||||
@@ -183,7 +184,7 @@ export function startGatewayMaintenanceTimers(params: {
|
||||
};
|
||||
|
||||
for (const [runId, entry] of params.chatAbortControllers) {
|
||||
if (now <= entry.expiresAtMs) {
|
||||
if (isFutureDateTimestampMs(entry.expiresAtMs, { nowMs: now })) {
|
||||
continue;
|
||||
}
|
||||
abortChatRunById(
|
||||
|
||||
Reference in New Issue
Block a user