mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-03 14:09:42 +02:00
fix: improve stability with memory leak fixes and atomic writes
Session Manager: - Store event handlers for proper cleanup on session stop - Add resetSessionManager() for test isolation State Store: - Use atomic write pattern (temp file + rename) to prevent corruption - Add tokenStats to AppState interface Subagent Watcher: - Clean up pendingToolCalls on agent completion - Add cleanupStaleAgents() for 24h+ old agents - Clear all state maps on stop() for clean restart Web Server: - Remove listeners from transcript watcher before stopping - Clean up respawn timers when session is deleted - Use cleanupSession() in spawn orchestrator for proper resource cleanup Frontend: - Close existing EventSource before reconnecting to prevent duplicates - Close failed connection before scheduling reconnect Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
+10
-7
@@ -1969,6 +1969,7 @@ export class WebServer extends EventEmitter {
|
||||
private stopTranscriptWatcher(sessionId: string): void {
|
||||
const watcher = this.transcriptWatchers.get(sessionId);
|
||||
if (watcher) {
|
||||
watcher.removeAllListeners(); // Prevent memory leaks from attached listeners
|
||||
watcher.stop();
|
||||
this.transcriptWatchers.delete(sessionId);
|
||||
}
|
||||
@@ -2247,6 +2248,12 @@ export class WebServer extends EventEmitter {
|
||||
controller.removeAllListeners();
|
||||
this.respawnControllers.delete(session.id);
|
||||
}
|
||||
// Also clean up the respawn timer to prevent orphaned timers
|
||||
const timerInfo = this.respawnTimers.get(session.id);
|
||||
if (timerInfo) {
|
||||
clearTimeout(timerInfo.timer);
|
||||
this.respawnTimers.delete(session.id);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(`[Server] Error cleaning up respawn controller for ${session.id}:`, err);
|
||||
}
|
||||
@@ -2485,13 +2492,9 @@ export class WebServer extends EventEmitter {
|
||||
return session ? session.totalCost : 0;
|
||||
},
|
||||
stopSession: async (sessionId: string) => {
|
||||
const session = this.sessions.get(sessionId);
|
||||
if (session) {
|
||||
await session.stop();
|
||||
this.sessions.delete(sessionId);
|
||||
this.broadcast('session:deleted', { id: sessionId });
|
||||
this.persistSessionState(session);
|
||||
}
|
||||
// Use cleanupSession to properly clean up all resources (respawn controllers,
|
||||
// run summary trackers, file streams, Ralph state, etc.)
|
||||
await this.cleanupSession(sessionId);
|
||||
},
|
||||
onSessionCompletion: (sessionId: string, handler: (phrase: string) => void) => {
|
||||
const session = this.sessions.get(sessionId);
|
||||
|
||||
Reference in New Issue
Block a user