@@ -10,6 +10,7 @@ export type BeforeAttempt<T> = (context: AttemptContext, options: AttemptOptions
1010export type CalculateDelay < T > = ( context : AttemptContext , options : AttemptOptions < T > ) => number ;
1111export type HandleError < T > = ( err : any , context : AttemptContext , options : AttemptOptions < T > ) => void ;
1212export type HandleTimeout < T > = ( context : AttemptContext , options : AttemptOptions < T > ) => Promise < T > ;
13+ export type HandleTotalTimeout < T > = ( options : AttemptOptions < T > ) => Promise < T > ;
1314
1415export interface AttemptOptions < T > {
1516 readonly delay : number ;
@@ -19,9 +20,11 @@ export interface AttemptOptions<T> {
1920 readonly factor : number ;
2021 readonly maxAttempts : number ;
2122 readonly timeout : number ;
23+ readonly totalTimeout : number ;
2224 readonly jitter : boolean ;
2325 readonly handleError : HandleError < T > | null ;
2426 readonly handleTimeout : HandleTimeout < T > | null ;
27+ readonly handleTotalTimeout : HandleTotalTimeout < T > | null ;
2528 readonly beforeAttempt : BeforeAttempt < T > | null ;
2629 readonly calculateDelay : CalculateDelay < T > | null ;
2730}
@@ -43,9 +46,11 @@ function applyDefaults<T> (options?: PartialAttemptOptions<T>): AttemptOptions<T
4346 factor : ( options . factor === undefined ) ? 0 : options . factor ,
4447 maxAttempts : ( options . maxAttempts === undefined ) ? 3 : options . maxAttempts ,
4548 timeout : ( options . timeout === undefined ) ? 0 : options . timeout ,
49+ totalTimeout : ( options . totalTimeout === undefined ) ? 0 : options . totalTimeout ,
4650 jitter : ( options . jitter === true ) ,
4751 handleError : ( options . handleError === undefined ) ? null : options . handleError ,
4852 handleTimeout : ( options . handleTimeout === undefined ) ? null : options . handleTimeout ,
53+ handleTotalTimeout : ( options . handleTotalTimeout === undefined ) ? null : options . handleTotalTimeout ,
4954 beforeAttempt : ( options . beforeAttempt === undefined ) ? null : options . beforeAttempt ,
5055 calculateDelay : ( options . calculateDelay === undefined ) ? null : options . calculateDelay
5156 } ;
@@ -88,7 +93,7 @@ export function defaultCalculateDelay<T> (context: AttemptContext, options: Atte
8893
8994export async function retry < T > (
9095 attemptFunc : AttemptFunction < T > ,
91- attemptOptions ?: PartialAttemptOptions < T > ) : Promise < T > {
96+ attemptOptions ?: PartialAttemptOptions < T > ) : Promise < any > {
9297
9398 const options = applyDefaults ( attemptOptions ) ;
9499
@@ -98,7 +103,8 @@ export async function retry<T> (
98103 'minDelay' ,
99104 'maxDelay' ,
100105 'maxAttempts' ,
101- 'timeout'
106+ 'timeout' ,
107+ 'totalTimeout'
102108 ] ) {
103109 const value : any = ( options as any ) [ prop ] ;
104110
@@ -161,7 +167,7 @@ export async function retry<T> (
161167 context . attemptsRemaining -- ;
162168 }
163169
164- if ( options . timeout ) {
170+ if ( options . timeout > 0 ) {
165171 return new Promise ( ( resolve , reject ) => {
166172 const timer = setTimeout ( ( ) => {
167173 if ( options . handleTimeout ) {
@@ -196,5 +202,30 @@ export async function retry<T> (
196202 await sleep ( initialDelay ) ;
197203 }
198204
199- return makeAttempt ( ) ;
205+ if ( options . totalTimeout > 0 ) {
206+ return new Promise ( ( resolve , reject ) => {
207+ const timer = setTimeout ( ( ) => {
208+ context . abort ( ) ;
209+ if ( options . handleTotalTimeout ) {
210+ resolve ( options . handleTotalTimeout ( options ) ) ;
211+ } else {
212+ const err : any = new Error ( `Total timeout (totalTimeout: ${ options . totalTimeout } )` ) ;
213+ err . code = 'TOTAL_TIMEOUT' ;
214+ reject ( err ) ;
215+ }
216+ } , options . totalTimeout ) ;
217+
218+ makeAttempt ( ) . then ( ( result : T ) => {
219+ clearTimeout ( timer ) ;
220+ resolve ( result ) ;
221+ } ) . catch ( ( err : any ) => {
222+ clearTimeout ( timer ) ;
223+ reject ( err ) ;
224+ } ) ;
225+ } ) ;
226+ } else {
227+ // No totalTimeout provided so wait indefinitely for the returned promise
228+ // to be resolved.
229+ return makeAttempt ( ) ;
230+ }
200231}
0 commit comments