import { FunctionPromiseIdentity, PromiseFn, PromiseLikeReturnType } from '../types'; import { wait } from './retryUtils'; type RetryPolicyOption = { retries: number; retryTime: number; retryFactor?: number; shouldRetry?: (error: ErrorObject) => boolean; }; function createRetryPolicy(retryPolicyOptions: RetryPolicyOption) { const { retries, retryTime, retryFactor = 2, shouldRetry = () => true } = retryPolicyOptions; return function applyRetryPolicy(fn: PromiseFn): FunctionPromiseIdentity { return async (...args: Parameters): Promise> => { let currentRetries = 0; let currentRetryTime = retryTime; return (async function executeRetry(...args: Parameters): Promise> { try { const result = await fn(...args); return result; } catch (error) { if (shouldRetry(error as ErrorObject) && currentRetries + 1 <= retries) { currentRetries++; await wait(currentRetryTime); currentRetryTime = currentRetryTime * retryFactor; return executeRetry(...args); } throw error; } })(...args); }; }; } export { createRetryPolicy };