import { HttpErrors } from '@loopback/rest' ; import { promisify } from 'util' ; import debugFactory from 'debug' ; const debug = debugFactory ( 'loopback:example:shopping' ) ; export interface TaskStatus < T > { done : boolean ; value ? : T | null ; } /**
 * A task that can be retried
 */ export interface Task < T > { run ( ) : Promise < TaskStatus < T > > ; description : string ; } /**
 * Options for retry
 */ export interface RetryOptions { /**
     * Maximum number of tries including the first run.
     */ maxTries ? : number ; /**
     * Milliseconds to wait after each try
     */ interval ? : number ; } param task param maxTries param interval export async function retry < T > ( task , { maxTries = 10 , interval = 100 } = { } ) { if ( maxTries < 1 ) maxTries = 1 ; let triesLeft = maxTries ; while ( true ) { debug ( 'Try %s (%d/%d)' , task . description , maxTries - triesLeft + 1 , maxTries ) ; const status = await task . run ( ) ; if ( status . done ) return status . value ! ; if ( -- triesLeft > 0 ) { debug ( 'Wait for %d ms' , interval ) ; await sleep ( interval ) ; } else { const msg = `Failed to ${ task . description } after ${ maxTries * interval } ms` ; debug ( '%s' , msg ) ; throw new HttpErrors . RequestTimeout ( msg ) ; } } } param ms export const sleep = promisify ( setTimeout ) ;