Merge branch 'feat/inda-383-daily-stat' into 'main'
[ProtonMail-WebClient.git] / packages / drive-store / utils / retryOnError.ts
blobd314ea8a302ffe1d661dce232f0e0c5390ab2693
1 import { wait } from '@proton/shared/lib/helpers/promise';
3 type Params<T> = {
4     fn: (...args: any) => Promise<T>;
5     beforeRetryCallback?: () => Promise<unknown[] | void>;
6     shouldRetryBasedOnError: (e: unknown) => boolean;
7     maxRetriesNumber: number;
8     backoff?: boolean;
9 };
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++) {
18         const temp = delay;
19         delay = delay + prevDelay;
20         prevDelay = temp;
21     }
23     return delay;
26 /**
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
34  */
35 const retryOnError = <ReturnType>({
36     fn,
37     beforeRetryCallback,
38     shouldRetryBasedOnError,
39     maxRetriesNumber,
40     backoff = false,
41 }: Params<ReturnType>): ((...args: any) => Promise<ReturnType>) => {
42     let retryCount = maxRetriesNumber;
44     const retry = async (...args: any): Promise<ReturnType> => {
45         try {
46             return await fn(...args);
47         } catch (error) {
48             if (retryCount > 0 && shouldRetryBasedOnError(error)) {
49                 retryCount--;
51                 if (beforeRetryCallback) {
52                     const newParams = await beforeRetryCallback();
53                     if (newParams) {
54                         if (backoff) {
55                             await wait(fibonacciExponentialBackoff(maxRetriesNumber - retryCount));
56                         }
57                         return retry(newParams);
58                     }
59                 }
61                 if (backoff) {
62                     await wait(fibonacciExponentialBackoff(maxRetriesNumber - retryCount));
63                 }
64                 return retry(...args);
65             }
67             throw error;
68         }
69     };
71     return retry;
74 export default retryOnError;