11import { IAssignmentType } from '@double-agent/collect-controller/interfaces/IAssignment' ;
22import * as http from 'http' ;
33import * as http2 from 'http2' ;
4+ import Config from '@double-agent/config' ;
45import Session from './Session' ;
56import PluginDelegate from './PluginDelegate' ;
67import BaseServer from '../servers/BaseServer' ;
@@ -10,6 +11,7 @@ let sessionIdCounter = 0;
1011export default class SessionTracker {
1112 private pluginDelegate : PluginDelegate = new PluginDelegate ( ) ;
1213 private sessions : { [ sessionId : string ] : Session } = { } ;
14+ private sessionExpiryById : { [ sessionId : string ] : NodeJS . Timeout } = { } ;
1315
1416 public async createSession (
1517 assignmentType : IAssignmentType ,
@@ -21,13 +23,18 @@ export default class SessionTracker {
2123 await session . startServers ( ) ;
2224
2325 this . sessions [ sessionId ] = session ;
26+ this . scheduleSessionExpiry ( sessionId ) ;
2427 return session ;
2528 }
2629
2730 public getSession ( sessionId : string ) : Session {
2831 return this . sessions [ sessionId ] ;
2932 }
3033
34+ public touchSession ( sessionId : string ) : void {
35+ this . scheduleSessionExpiry ( sessionId ) ;
36+ }
37+
3138 public getSessionIdFromServerRequest (
3239 server : BaseServer ,
3340 req : http . IncomingMessage | http2 . Http2ServerRequest ,
@@ -48,12 +55,40 @@ export default class SessionTracker {
4855
4956 public async deleteSession ( sessionId : string ) : Promise < void > {
5057 if ( ! this . sessions [ sessionId ] ) return ;
58+ this . clearSessionExpiry ( sessionId ) ;
5159 await this . sessions [ sessionId ] . close ( ) ;
5260 delete this . sessions [ sessionId ] ;
5361 }
5462
5563 public async shutdown ( ) : Promise < void > {
5664 await Promise . allSettled ( Object . values ( this . sessions ) . map ( ( x ) => x . close ( ) ) ) ;
5765 await Promise . allSettled ( this . pluginDelegate . plugins . map ( ( x ) => x . stop ( ) ) ) ;
66+ this . clearAllSessionExpiry ( ) ;
67+ }
68+
69+ private scheduleSessionExpiry ( sessionId : string ) : void {
70+ const ttlMs = Config . collect . sessionTtlMs ;
71+ if ( ! ttlMs || ttlMs <= 0 ) return ;
72+ this . clearSessionExpiry ( sessionId ) ;
73+ const timeout = setTimeout ( ( ) => {
74+ console . warn ( 'Session expired due to inactivity/ttl' , sessionId ) ;
75+ void this . deleteSession ( sessionId ) ;
76+ } , ttlMs ) ;
77+ timeout . unref ( ) ;
78+ this . sessionExpiryById [ sessionId ] = timeout ;
79+ }
80+
81+ private clearSessionExpiry ( sessionId : string ) : void {
82+ const timeout = this . sessionExpiryById [ sessionId ] ;
83+ if ( timeout ) {
84+ clearTimeout ( timeout ) ;
85+ delete this . sessionExpiryById [ sessionId ] ;
86+ }
87+ }
88+
89+ private clearAllSessionExpiry ( ) : void {
90+ for ( const sessionId of Object . keys ( this . sessionExpiryById ) ) {
91+ this . clearSessionExpiry ( sessionId ) ;
92+ }
5893 }
5994}
0 commit comments