11import ISessionMeta from '@secret-agent/interfaces/ISessionMeta' ;
22import { CanceledPromiseError } from '@secret-agent/commons/interfaces/IPendingWaitEvent' ;
33import Queue from '@secret-agent/commons/Queue' ;
4+ import ICoreRequestPayload from '@secret-agent/interfaces/ICoreRequestPayload' ;
45import ConnectionToCore from '../connections/ConnectionToCore' ;
56import { convertJsPathArgs } from './SetupAwaitedHandler' ;
7+ import ICommandCounter from '../interfaces/ICommandCounter' ;
68
79export default class CoreCommandQueue {
8- public lastCommandId = 0 ;
10+ public get lastCommandId ( ) : number {
11+ return this . commandCounter ?. lastCommandId ;
12+ }
13+
14+ public get nextCommandId ( ) : number {
15+ return this . commandCounter ?. nextCommandId ;
16+ }
917
1018 private readonly internalState : {
1119 queue : Queue ;
12- batchSendCommands : { [ command : string ] : any [ ] [ ] } ;
20+ commandsToRecord : ICoreRequestPayload [ 'recordCommands' ] ;
1321 } ;
1422
23+ private readonly commandCounter ?: ICommandCounter ;
1524 private readonly sessionMarker : string = '' ;
25+ private readonly meta : ISessionMeta ;
26+ private readonly connection : ConnectionToCore ;
27+ private flushOnTimeout : NodeJS . Timeout ;
1628
1729 private get internalQueue ( ) : Queue {
1830 return this . internalState . queue ;
1931 }
2032
2133 constructor (
22- private readonly meta : ( ISessionMeta & { sessionName : string } ) | null ,
23- private readonly connection : ConnectionToCore ,
34+ meta : ( ISessionMeta & { sessionName : string } ) | null ,
35+ connection : ConnectionToCore ,
36+ commandCounter : ICommandCounter ,
2437 internalState ?: CoreCommandQueue [ 'internalState' ] ,
2538 ) {
39+ this . connection = connection ;
2640 if ( meta ) {
2741 const markers = [
2842 '' . padEnd ( 50 , '-' ) ,
@@ -31,38 +45,47 @@ export default class CoreCommandQueue {
3145 '' . padEnd ( 50 , '-' ) ,
3246 ] . join ( '\n' ) ;
3347 this . sessionMarker = `\n\n${ markers } ` ;
48+ this . meta = { sessionId : meta . sessionId , tabId : meta . tabId , frameId : meta . frameId } ;
3449 }
50+ this . commandCounter = commandCounter ;
3551
36- if ( internalState ) {
37- this . internalState = internalState ;
38- } else {
39- this . internalState = {
40- queue : new Queue ( 'CORE COMMANDS' , 1 ) ,
41- batchSendCommands : { } ,
42- } ;
43- }
52+ this . internalState = internalState ?? {
53+ queue : new Queue ( 'CORE COMMANDS' , 1 ) ,
54+ commandsToRecord : [ ] ,
55+ } ;
4456 }
4557
46- public queueBatchedCommand ( command : string , ...args : any [ ] ) : void {
47- this . internalState . batchSendCommands [ command ] ??= [ ] ;
48- this . internalState . batchSendCommands [ command ] . push ( args ) ;
49- if ( this . internalState . batchSendCommands [ command ] . length > 1000 ) this . flush ( ) . catch ( ( ) => null ) ;
50- this . internalQueue . enqueue ( this . flush . bind ( this ) ) ;
58+ public record ( command : { command : string ; args : any [ ] ; commandId ?: number } ) : void {
59+ this . internalState . commandsToRecord . push ( {
60+ ...command ,
61+ startDate : new Date ( ) ,
62+ } ) ;
63+ if ( this . internalState . commandsToRecord . length > 1000 ) {
64+ this . flush ( ) . catch ( ( ) => null ) ;
65+ } else if ( ! this . flushOnTimeout ) {
66+ this . flushOnTimeout = setTimeout ( ( ) => this . flush ( ) , 1e3 ) . unref ( ) ;
67+ }
5168 }
5269
5370 public async flush ( ) : Promise < void > {
54- for ( const [ command , args ] of Object . entries ( this . internalState . batchSendCommands ) ) {
55- delete this . internalState . batchSendCommands [ command ] ;
56- if ( ! args ) continue ;
57- await this . connection . sendRequest ( {
58- meta : this . meta ,
59- command,
60- args,
61- } ) ;
62- }
71+ clearTimeout ( this . flushOnTimeout ) ;
72+ this . flushOnTimeout = null ;
73+ if ( ! this . internalState . commandsToRecord . length ) return ;
74+ const recordCommands = [ ...this . internalState . commandsToRecord ] ;
75+ this . internalState . commandsToRecord . length = 0 ;
76+
77+ await this . connection . sendRequest ( {
78+ meta : this . meta ,
79+ command : 'Session.flush' ,
80+ startDate : new Date ( ) ,
81+ args : [ ] ,
82+ recordCommands,
83+ } ) ;
6384 }
6485
6586 public run < T > ( command : string , ...args : any [ ] ) : Promise < T > {
87+ clearTimeout ( this . flushOnTimeout ) ;
88+ this . flushOnTimeout = null ;
6689 if ( this . connection . isDisconnecting ) {
6790 return Promise . resolve ( null ) ;
6891 }
@@ -71,17 +94,24 @@ export default class CoreCommandQueue {
7194 convertJsPathArgs ( arg ) ;
7295 }
7396 }
97+ const startTime = new Date ( ) ;
98+ const commandId = this . nextCommandId ;
7499 return this . internalQueue
75100 . run < T > ( async ( ) => {
101+ const recordCommands = [ ...this . internalState . commandsToRecord ] ;
102+ this . internalState . commandsToRecord . length = 0 ;
103+
76104 const response = await this . connection . sendRequest ( {
77105 meta : this . meta ,
78106 command,
79107 args,
108+ startDate : startTime ,
109+ commandId,
110+ recordCommands,
80111 } ) ;
81112
82113 let data : T = null ;
83114 if ( response ) {
84- this . lastCommandId = response . commandId ;
85115 data = response . data ;
86116 }
87117 return data ;
@@ -101,6 +131,6 @@ export default class CoreCommandQueue {
101131 }
102132
103133 public createSharedQueue ( meta : ISessionMeta & { sessionName : string } ) : CoreCommandQueue {
104- return new CoreCommandQueue ( meta , this . connection , this . internalState ) ;
134+ return new CoreCommandQueue ( meta , this . connection , this . commandCounter , this . internalState ) ;
105135 }
106136}
0 commit comments