@@ -9,12 +9,20 @@ import ConnectionToCore from '../connections/ConnectionToCore';
99import ConnectionFactory from '../connections/ConnectionFactory' ;
1010import DisconnectedFromCoreError from '../connections/DisconnectedFromCoreError' ;
1111
12- type SettledDispatchesBySessionId = { [ sessionId : string ] : { args : any ; error ?: Error } } ;
13- type PendingDispatch = { resolution : Promise < Error | void > ; sessionId ?: string ; args : any } ;
12+ type SettledDispatchesBySessionId = {
13+ [ sessionId : string ] : { args : any ; error ?: Error ; retries : number } ;
14+ } ;
15+ type PendingDispatch = {
16+ resolution : Promise < Error | void > ;
17+ sessionId ?: string ;
18+ args : any ;
19+ retries : number ;
20+ } ;
1421
1522const { log } = Log ( module ) ;
1623
1724export default class Handler {
25+ public disconnectedDispatchRetries = 3 ;
1826 public defaultAgentOptions : IAgentCreateOptions = { } ;
1927 public get coreHosts ( ) : Promise < string [ ] > {
2028 return Promise . all ( this . connections . map ( x => x . hostOrError ) ) . then ( x => {
@@ -30,6 +38,8 @@ export default class Handler {
3038 private readonly connections : ConnectionToCore [ ] = [ ] ;
3139 private readonly dispatches : PendingDispatch [ ] = [ ] ;
3240
41+ private isClosing = false ;
42+
3343 constructor ( ...connectionOptions : ( IConnectionToCoreOptions | ConnectionToCore ) [ ] ) {
3444 if ( ! connectionOptions . length ) {
3545 connectionOptions . push ( { } ) ;
@@ -68,14 +78,25 @@ export default class Handler {
6878 runFn : ( agent : Agent , args ?: T ) => Promise < void > ,
6979 args ?: T ,
7080 createAgentOptions ?: IAgentCreateOptions ,
81+ pendingDispatch ?: PendingDispatch ,
7182 ) : void {
7283 const options = {
7384 ...this . defaultAgentOptions ,
7485 ...createAgentOptions ,
7586 } ;
87+
88+ const dispatched : PendingDispatch = pendingDispatch ?? { args, resolution : null , retries : 0 } ;
89+
90+ // if no available connection, return
7691 const connection = this . getConnection ( ) ;
92+ if ( ! connection ) {
93+ dispatched . resolution = Promise . resolve (
94+ new Error ( "There aren't any connections available to dispatch this agent" ) ,
95+ ) ;
96+ this . dispatches . push ( dispatched ) ;
97+ return ;
98+ }
7799
78- const dispatched : PendingDispatch = { args, resolution : null } ;
79100 dispatched . resolution = connection
80101 . useAgent ( options , async agent => {
81102 try {
@@ -85,7 +106,16 @@ export default class Handler {
85106 await agent . close ( ) ;
86107 }
87108 } )
88- . catch ( ( err : Error ) => err ) ;
109+ . catch ( err => {
110+ const canRetry =
111+ ! dispatched . sessionId && dispatched . retries < this . disconnectedDispatchRetries ;
112+ if ( canRetry && ! this . isClosing && this . connections . length ) {
113+ dispatched . retries += 1 ;
114+ return this . dispatchAgent ( runFn , args , createAgentOptions , dispatched ) ;
115+ }
116+
117+ return err ;
118+ } ) ;
89119
90120 this . dispatches . push ( dispatched ) ;
91121 }
@@ -144,9 +174,9 @@ export default class Handler {
144174 this . dispatches . length = 0 ;
145175
146176 await Promise . all ( dispatches . map ( x => x . resolution ) ) ;
147- for ( const { sessionId, resolution, args } of dispatches ) {
177+ for ( const { sessionId, resolution, args, retries } of dispatches ) {
148178 const error = < Error > await resolution ;
149- result [ sessionId ] = { args, error } ;
179+ result [ sessionId ] = { args, error, retries } ;
150180 }
151181
152182 await new Promise ( setImmediate ) ;
@@ -156,15 +186,21 @@ export default class Handler {
156186 }
157187
158188 public async close ( error ?: Error ) : Promise < void > {
189+ if ( this . isClosing ) return ;
190+ this . isClosing = true ;
159191 // eslint-disable-next-line promise/no-promise-in-callback
160192 await Promise . all ( this . connections . map ( x => x . disconnect ( error ) ) ) ;
161193 }
162194
163- private getConnection ( ) : ConnectionToCore {
195+ private getAvailableConnections ( ) : ConnectionToCore [ ] {
164196 // prefer a connection that can create a session right now
165197 let connections = this . connections . filter ( x => x . canCreateSessionNow ( ) ) ;
166198 if ( ! connections . length ) connections = this . connections . filter ( x => ! x . isDisconnecting ) ;
167- return pickRandom ( connections ) ;
199+ return connections ;
200+ }
201+
202+ private getConnection ( ) : ConnectionToCore {
203+ return pickRandom ( this . getAvailableConnections ( ) ) ;
168204 }
169205
170206 private registerUnhandledExceptionHandlers ( ) : void {
0 commit comments