From 3b99312fdba0f3f3a35ff5ab78a3fa7bc2e87736 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Tue, 1 Jul 2025 12:48:41 +0100 Subject: [PATCH] fix: Improve heartbeat handling and session.json debounce cleanup - Echo heartbeat messages back to clients for better connection monitoring - Properly clear debounce timer references to prevent memory leaks - Pass client socket to message handler for proper heartbeat responses --- web/src/server/pty/pty-manager.ts | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/web/src/server/pty/pty-manager.ts b/web/src/server/pty/pty-manager.ts index 1802e6eb..b22b8028 100644 --- a/web/src/server/pty/pty-manager.ts +++ b/web/src/server/pty/pty-manager.ts @@ -719,7 +719,7 @@ export class PtyManager extends EventEmitter { parser.addData(chunk); for (const { type, payload } of parser.parseMessages()) { - this.handleSocketMessage(session, type, payload); + this.handleSocketMessage(session, type, payload, client); } }); @@ -750,7 +750,12 @@ export class PtyManager extends EventEmitter { /** * Handle incoming socket messages */ - private handleSocketMessage(session: PtySession, type: MessageType, payload: Buffer): void { + private handleSocketMessage( + session: PtySession, + type: MessageType, + payload: Buffer, + client?: net.Socket + ): void { try { const data = parsePayload(type, payload); @@ -773,7 +778,11 @@ export class PtyManager extends EventEmitter { } case MessageType.HEARTBEAT: - // Echo heartbeat back (could add heartbeat response later) + // Echo heartbeat back to the client + if (client && !client.destroyed) { + const heartbeatFrame = frameMessage(MessageType.HEARTBEAT, Buffer.alloc(0)); + client.write(heartbeatFrame); + } break; default: @@ -802,8 +811,9 @@ export class PtyManager extends EventEmitter { debounceTimer = setTimeout(() => { this.handleSessionJsonChange(session); - // Clear the timer reference after execution + // Clear both timer references after execution session.sessionJsonDebounceTimer = null; + debounceTimer = null; }, 100); // Update the session's timer reference @@ -811,6 +821,9 @@ export class PtyManager extends EventEmitter { } }); + // Store watcher for cleanup BEFORE setting up error handler + session.sessionJsonWatcher = watcher; + // Add error handling for watcher watcher.on('error', (error) => { logger.error(`Session.json watcher failed for ${session.id}:`, error); @@ -823,9 +836,6 @@ export class PtyManager extends EventEmitter { } }); - // Store watcher for cleanup - session.sessionJsonWatcher = watcher; - // Unref the watcher so it doesn't keep the process alive watcher.unref();