fix(gateway): cancel delayed maintenance on shutdown

This commit is contained in:
Vincent Koc
2026-05-05 16:01:17 -07:00
parent 16454f5c7a
commit 1e1903487f
3 changed files with 32 additions and 2 deletions

View File

@@ -86,6 +86,7 @@ Docs: https://docs.openclaw.ai
### Fixes
- Gateway/shutdown: cancel delayed post-ready maintenance during close and suppress maintenance/cron startup after quick restarts, preventing orphaned background timers. Thanks @vincentkoc.
- Agents/generated media: treat attachment-style message tool actions as completed chat sends, preventing duplicate fallback media posts when generated files were already uploaded.
- Control UI/sessions: show each session's agent runtime in the Sessions table and allow filtering by runtime labels, matching the Agents panel runtime wording. Thanks @vincentkoc.
- Discord/streaming: show live reasoning text in progress drafts instead of a bare `Reasoning` status line.

View File

@@ -56,9 +56,24 @@ describe("gateway startup import boundaries", () => {
const closeStart = serverImpl.indexOf("close: async (opts)");
const hookStart = serverImpl.indexOf("runGlobalGatewayStopSafely", closeStart);
const markStart = serverImpl.indexOf("markClosePreludeStarted();", closeStart);
const markHelperStart = serverImpl.indexOf("const markClosePreludeStarted = () => {");
const markHelperEnd = serverImpl.indexOf("};", markHelperStart);
const postReadyStart = serverImpl.indexOf("scheduleGatewayPostReadyMaintenance({");
const postReadyEnd = serverImpl.indexOf("});", postReadyStart);
const postReadyBlock = serverImpl.slice(postReadyStart, postReadyEnd);
expect(closeStart).toBeGreaterThan(-1);
expect(markStart).toBeGreaterThan(closeStart);
expect(markStart).toBeLessThan(hookStart);
expect(markHelperStart).toBeGreaterThan(-1);
expect(serverImpl.slice(markHelperStart, markHelperEnd)).toContain(
"clearPostReadyMaintenanceTimer();",
);
expect(postReadyStart).toBeGreaterThan(-1);
expect(postReadyBlock).toContain("isClosing: () => closePreludeStarted");
expect(postReadyBlock).toContain("if (closePreludeStarted)");
expect(postReadyBlock).toContain(
"shouldStartCron: () => !closePreludeStarted && !gatewayCronStartHandled",
);
});
});

View File

@@ -1524,14 +1524,28 @@ export async function startGatewayServer(
onStarted: () => {
postReadyMaintenanceTimer = null;
},
startMaintenance: earlyRuntime.startMaintenance,
startMaintenance: async () => {
if (closePreludeStarted) {
return null;
}
return earlyRuntime.startMaintenance();
},
applyMaintenance: (maintenance) => {
if (closePreludeStarted) {
clearInterval(maintenance.tickInterval);
clearInterval(maintenance.healthInterval);
clearInterval(maintenance.dedupeCleanup);
if (maintenance.mediaCleanup) {
clearInterval(maintenance.mediaCleanup);
}
return;
}
runtimeState.tickInterval = maintenance.tickInterval;
runtimeState.healthInterval = maintenance.healthInterval;
runtimeState.dedupeCleanup = maintenance.dedupeCleanup;
runtimeState.mediaCleanup = maintenance.mediaCleanup;
},
shouldStartCron: () => !gatewayCronStartHandled,
shouldStartCron: () => !closePreludeStarted && !gatewayCronStartHandled,
markCronStartHandled: () => {
gatewayCronStartHandled = true;
},