All files / src/utils RetryUtils.ts

100% Statements 14/14
75% Branches 6/8
83.33% Functions 5/6
100% Lines 13/13

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58    1x                           66x       9x                 66x 66x 80x   80x   24x 10x   14x 14x   14x                         14x      
// SPDX-License-Identifier: Apache-2.0
 
export class RetryUtils {
 
  /**
   * Retries a task up to a specified number of times.
   *
   * @param {() => Promise<T>} task - The task to retry.
   * @param {Object} options - The options for the retry.
   * @param [options.maxAttempts=3] - The maximum number of attempts.
   * @param [options.backOff=500] - The time to wait between attempts in milliseconds.
   * @param [options.doOnRetry=(error, attempt) => {}] - The function to call on each retry.
   * @returns {Promise<T>} - A promise that resolves with the result of the task.
   * @template T
   */
  public static async retryTask<T>(
    task: () => Promise<T>,
    {
      maxRetries = 3,
      backOff = 500,
      shouldRetry = (_error: unknown) => true,
      doOnRetry = (_error: unknown) => {},
    }: {
      maxRetries?: number;
      backOff?: number;
      shouldRetry?: (error: unknown) => boolean;
      doOnRetry?: (error: unknown) => void;
    } = {}
  ): Promise<T> {
    let retries = 0;
    while (retries < maxRetries) {
      try {
        // eslint-disable-next-line no-await-in-loop
        return await task();
      } catch (error) {
        if (!shouldRetry(error) || retries === maxRetries - 1) {
          throw error;
        }
        doOnRetry(error);
        await this.delay(backOff);
      }
      retries += 1;
    }
    /* istanbul ignore next */
    throw new Error('Unreachable code');
  }
 
  /**
   * Delays the execution of the task.
   * @param ms The time to wait in milliseconds.
   * @returns {Promise<void>} A promise that resolves after the delay.
   * @private
   */
  private static delay(ms: number): Promise<void> {
    return new Promise((resolve) => setTimeout(resolve, ms));
  }
}