Skip to content

Commit b668a4f

Browse files
ISI-522: clear hook cleanup interval on service.stop()
registerHooks now returns a disposer that clears the 60s setInterval stale-session sweeper. index.ts captures it and invokes it from service.stop() so the timer is released on plugin shutdown/reload instead of leaking across lifecycles. Co-Authored-By: Paperclip <noreply@paperclip.ing>
1 parent 907e51a commit b668a4f

2 files changed

Lines changed: 16 additions & 4 deletions

File tree

index.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,9 @@ const otelObservabilityPlugin = {
5959
// registering them later inside service.start() means our listeners
6060
// are never seen by the gateway. We register here and pass a lazy
6161
// telemetry getter; hooks no-op until start() has built the runtime.
62-
registerHooks(api, () => telemetry, config);
62+
// registerHooks returns a cleanup fn (clears the stale-session sweeper
63+
// interval) so service.stop() doesn't leak the timer across reloads.
64+
let stopHooks: (() => void) | null = registerHooks(api, () => telemetry, config);
6365

6466
// ── RPC: status endpoint ────────────────────────────────────────
6567

@@ -142,6 +144,10 @@ const otelObservabilityPlugin = {
142144
},
143145

144146
stop: async () => {
147+
if (stopHooks) {
148+
stopHooks();
149+
stopHooks = null;
150+
}
145151
if (unsubscribeDiagnostics) {
146152
unsubscribeDiagnostics();
147153
unsubscribeDiagnostics = null;

src/hooks.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ export function registerHooks(
5353
api: any,
5454
getTelemetry: () => TelemetryRuntime | null,
5555
config: OtelObservabilityConfig
56-
): void {
56+
): () => void {
5757
const logger = api.logger;
5858

5959
const buildSecurityCounters = (counters: TelemetryRuntime["counters"]): SecurityCounters => ({
@@ -540,8 +540,10 @@ export function registerHooks(
540540
logger.info("[otel] Registered gateway:startup hook (via api.registerHook)");
541541

542542
// ── Periodic cleanup ─────────────────────────────────────────────
543-
// Safety net: clean up stale session contexts (e.g., if agent_end never fires)
544-
setInterval(() => {
543+
// Safety net: clean up stale session contexts (e.g., if agent_end never fires).
544+
// The handle is returned to the caller so service.stop() can clear it and
545+
// avoid leaking timers across plugin reload / shutdown.
546+
const cleanupInterval = setInterval(() => {
545547
const now = Date.now();
546548
const maxAge = 5 * 60 * 1000; // 5 minutes
547549
for (const [key, ctx] of sessionContextMap) {
@@ -555,4 +557,8 @@ export function registerHooks(
555557
}
556558
}
557559
}, 60_000);
560+
561+
return () => {
562+
clearInterval(cleanupInterval);
563+
};
558564
}

0 commit comments

Comments
 (0)