1 import { wait } from '@proton/shared/lib/helpers/promise';
4 fn: (...args: any) => Promise<T>;
5 beforeRetryCallback?: () => Promise<unknown[] | void>;
6 shouldRetryBasedOnError: (e: unknown) => boolean;
7 maxRetriesNumber: number;
11 function fibonacciExponentialBackoff(attempt: number) {
12 const initialDelay = 30 * 1000; // Initial delay in seconds
14 let delay = initialDelay;
15 let prevDelay = initialDelay;
17 for (let i = 2; i <= attempt; i++) {
19 delay = delay + prevDelay;
27 * @param {Object} config
28 * @param config.fn - The main async function to execute/retry on failure
29 * @param config.beforeRetryCallback - The function to execute before retry attempt; Allows to update parameters
30 * for the main function by returning then in an arrray
31 * @param config.shouldRetryBasedOnError – Error validation function. If returns true, the main callback's
32 * considered ready to be executed again
33 * @param {number} config.maxRetriesNumber - number of retries until the exection fails
35 const retryOnError = <ReturnType>({
38 shouldRetryBasedOnError,
41 }: Params<ReturnType>): ((...args: any) => Promise<ReturnType>) => {
42 let retryCount = maxRetriesNumber;
44 const retry = async (...args: any): Promise<ReturnType> => {
46 return await fn(...args);
48 if (retryCount > 0 && shouldRetryBasedOnError(error)) {
51 if (beforeRetryCallback) {
52 const newParams = await beforeRetryCallback();
55 await wait(fibonacciExponentialBackoff(maxRetriesNumber - retryCount));
57 return retry(newParams);
62 await wait(fibonacciExponentialBackoff(maxRetriesNumber - retryCount));
64 return retry(...args);
74 export default retryOnError;