@@ -113,6 +113,7 @@ export default class IntervalClient {
113113 #completeHttpRequestDelayMs: number = 3000
114114 #completeShutdownDelayMs: number = 3000
115115 #retryIntervalMs: number = 3000
116+ #maxResendAttempts: number = 10
116117 #pingIntervalMs: number = 30_000
117118 #closeUnresponsiveConnectionTimeoutMs: number = 3 * 60 * 1000 // 3 minutes
118119 #reinitializeBatchTimeoutMs: number = 200
@@ -175,6 +176,10 @@ export default class IntervalClient {
175176 this . #completeHttpRequestDelayMs = config . completeHttpRequestDelayMs
176177 }
177178
179+ if ( config . maxResendAttempts && config . maxResendAttempts > 0 ) {
180+ this . #maxResendAttempts = config . maxResendAttempts
181+ }
182+
178183 this . #httpEndpoint = getHttpEndpoint ( this . #endpoint)
179184
180185 if ( config . setHostHandlers ) {
@@ -499,7 +504,8 @@ export default class IntervalClient {
499504 )
500505 : new Map ( this . #pendingIOCalls)
501506
502- while ( toResend . size > 0 ) {
507+ let attemptNumber = 1
508+ while ( toResend . size > 0 && attemptNumber <= this . #maxResendAttempts) {
503509 await Promise . allSettled (
504510 Array . from ( toResend . entries ( ) ) . map ( ( [ transactionId , ioCall ] ) =>
505511 this . #send( 'SEND_IO_CALL' , {
@@ -534,15 +540,16 @@ export default class IntervalClient {
534540 this . #logger. debug ( 'Failed resending pending IO call:' , err )
535541 }
536542
543+ const retrySleepMs = this . #retryIntervalMs * attemptNumber
537544 this . #logger. debug (
538- `Trying again in ${ Math . round (
539- this . #retryIntervalMs / 1000
540- ) } s...`
545+ `Trying again in ${ Math . round ( retrySleepMs / 1000 ) } s...`
541546 )
542- await sleep ( this . #retryIntervalMs )
547+ await sleep ( retrySleepMs )
543548 } )
544549 )
545550 )
551+
552+ attemptNumber ++
546553 }
547554 }
548555
@@ -560,7 +567,8 @@ export default class IntervalClient {
560567 )
561568 : new Map ( this . #pendingPageLayouts)
562569
563- while ( toResend . size > 0 ) {
570+ let attemptNumber = 1
571+ while ( toResend . size > 0 && attemptNumber <= this . #maxResendAttempts) {
564572 await Promise . allSettled (
565573 Array . from ( toResend . entries ( ) ) . map ( ( [ pageKey , page ] ) =>
566574 this . #send( 'SEND_PAGE' , {
@@ -595,15 +603,16 @@ export default class IntervalClient {
595603 this . #logger. debug ( 'Failed resending pending page layout:' , err )
596604 }
597605
606+ const retrySleepMs = this . #retryIntervalMs * attemptNumber
598607 this . #logger. debug (
599- `Trying again in ${ Math . round (
600- this . #retryIntervalMs / 1000
601- ) } s...`
608+ `Trying again in ${ Math . round ( retrySleepMs / 1000 ) } s...`
602609 )
603- await sleep ( this . #retryIntervalMs )
610+ await sleep ( retrySleepMs )
604611 } )
605612 )
606613 )
614+
615+ attemptNumber ++
607616 }
608617 }
609618
@@ -621,7 +630,8 @@ export default class IntervalClient {
621630 )
622631 : new Map ( this . #transactionLoadingStates)
623632
624- while ( toResend . size > 0 ) {
633+ let attemptNumber = 0
634+ while ( toResend . size > 0 && attemptNumber <= this . #maxResendAttempts) {
625635 await Promise . allSettled (
626636 Array . from ( toResend . entries ( ) ) . map ( ( [ transactionId , loadingState ] ) =>
627637 this . #send( 'SEND_LOADING_CALL' , {
@@ -657,15 +667,16 @@ export default class IntervalClient {
657667 this . #logger. debug ( 'Failed resending pending IO call:' , err )
658668 }
659669
670+ const retrySleepMs = this . #retryIntervalMs * attemptNumber
660671 this . #logger. debug (
661- `Trying again in ${ Math . round (
662- this . #retryIntervalMs / 1000
663- ) } s...`
672+ `Trying again in ${ Math . round ( retrySleepMs / 1000 ) } s...`
664673 )
665- await sleep ( this . #retryIntervalMs )
674+ await sleep ( retrySleepMs )
666675 } )
667676 )
668677 )
678+
679+ attemptNumber ++
669680 }
670681 }
671682
@@ -2003,27 +2014,41 @@ export default class IntervalClient {
20032014 this . #logger. debug ( 'Error from peer RPC' , err )
20042015 }
20052016
2006- while ( true ) {
2017+ for (
2018+ let attemptNumber = 1 ;
2019+ attemptNumber <= this . #maxResendAttempts;
2020+ attemptNumber ++
2021+ ) {
20072022 try {
20082023 this . #logger. debug ( 'Sending via server' , methodName , inputs )
2009- return await this . #serverRpc. send ( methodName , {
2010- ...inputs ,
2011- skipClientCall,
2012- } )
2024+ return await this . #serverRpc. send (
2025+ methodName ,
2026+ {
2027+ ...inputs ,
2028+ skipClientCall,
2029+ } ,
2030+ {
2031+ timeoutFactor : attemptNumber ,
2032+ }
2033+ )
20132034 } catch ( err ) {
2035+ const sleepTimeBeforeRetrying = this . #retryIntervalMs * attemptNumber
2036+
20142037 if ( err instanceof TimeoutError ) {
20152038 this . #log. debug (
20162039 `RPC call timed out, retrying in ${ Math . round (
2017- this . #retryIntervalMs / 1000
2040+ sleepTimeBeforeRetrying / 1000
20182041 ) } s...`
20192042 )
20202043 this . #log. debug ( err )
2021- sleep ( this . #retryIntervalMs )
2044+ sleep ( sleepTimeBeforeRetrying )
20222045 } else {
20232046 throw err
20242047 }
20252048 }
20262049 }
2050+
2051+ throw new IntervalError ( 'Maximum failed resend attempts reached, aborting.' )
20272052 }
20282053
20292054 /**
0 commit comments