Explorar el Código

fix(multiplexer): avoid missing cleanup for sessions never seen in status

m.seomun hace 2 meses
padre
commit
6dede95654
Se han modificado 2 ficheros con 60 adiciones y 0 borrados
  1. 55 0
      src/multiplexer/session-manager.test.ts
  2. 5 0
      src/multiplexer/session-manager.ts

+ 55 - 0
src/multiplexer/session-manager.test.ts

@@ -390,6 +390,61 @@ describe('MultiplexerSessionManager', () => {
       expect(mockMultiplexer.closePane).not.toHaveBeenCalled();
     });
 
+    test('does not close missing session that was never seen in status', async () => {
+      const ctx = createMockContext();
+      mockMultiplexer.spawnPane.mockResolvedValue({
+        success: true,
+        paneId: 'p-never-seen',
+      });
+      const manager = new MultiplexerSessionManager(
+        ctx,
+        defaultMultiplexerConfig,
+      );
+
+      await manager.onSessionCreated({
+        type: 'session.created',
+        properties: { info: { id: 'never-seen', parentID: 'p1' } },
+      });
+
+      const tracked = (manager as any).sessions.get('never-seen');
+      tracked.missingSince = Date.now() - 60_000;
+
+      setMockSessionStatuses({});
+      await (manager as any).pollSessions();
+
+      expect(mockMultiplexer.closePane).not.toHaveBeenCalled();
+    });
+
+    test('keeps missing cleanup for sessions previously seen in status', async () => {
+      const ctx = createMockContext();
+      mockMultiplexer.spawnPane.mockResolvedValue({
+        success: true,
+        paneId: 'p-seen-before-missing',
+      });
+      const manager = new MultiplexerSessionManager(
+        ctx,
+        defaultMultiplexerConfig,
+      );
+
+      await manager.onSessionCreated({
+        type: 'session.created',
+        properties: { info: { id: 'seen-before-missing', parentID: 'p1' } },
+      });
+
+      setMockSessionStatuses({ 'seen-before-missing': { type: 'busy' } });
+      await (manager as any).pollSessions();
+
+      const tracked = (manager as any).sessions.get('seen-before-missing');
+      tracked.missingSince = Date.now() - 60_000;
+
+      setMockSessionStatuses({});
+      await (manager as any).pollSessions();
+
+      expect(mockMultiplexer.closePane).toHaveBeenCalledWith(
+        'p-seen-before-missing',
+      );
+    });
+
     test('polls the actual serverUrl instead of the plugin SDK default URL', async () => {
       const ctx = createMockContext({
         serverUrl: 'http://127.0.0.1:63871/',

+ 5 - 0
src/multiplexer/session-manager.ts

@@ -16,6 +16,7 @@ interface TrackedSession {
   directory: string;
   createdAt: number;
   lastSeenAt: number;
+  seenInStatus: boolean;
   missingSince?: number;
 }
 
@@ -221,6 +222,7 @@ export class MultiplexerSessionManager {
         directory,
         createdAt: now,
         lastSeenAt: now,
+        seenInStatus: false,
       });
 
       log('[multiplexer-session-manager] pane spawned', {
@@ -330,12 +332,14 @@ export class MultiplexerSessionManager {
 
         if (status) {
           tracked.lastSeenAt = now;
+          tracked.seenInStatus = true;
           tracked.missingSince = undefined;
         } else if (!tracked.missingSince) {
           tracked.missingSince = now;
         }
 
         const missingTooLong =
+          tracked.seenInStatus &&
           !!tracked.missingSince &&
           now - tracked.missingSince >= SESSION_MISSING_GRACE_MS;
         const isTimedOut = now - tracked.createdAt > SESSION_TIMEOUT_MS;
@@ -505,6 +509,7 @@ export class MultiplexerSessionManager {
         directory: known.directory,
         createdAt: now,
         lastSeenAt: now,
+        seenInStatus: false,
       });
 
       log('[multiplexer-session-manager] pane respawned on busy', {