UNPKG

@openmrs/esm-utils

Version:
46 lines (45 loc) 1.84 kB
/** @module @category Utility */ /** * Options for configuring the behavior of the {@link retry} function. */ /** * Executes the specified function and retries executing on failure with a custom backoff strategy * defined by the options. * * If not configured otherwise, this function uses the following default options: * * Retries 5 times beyond the initial attempt. * * Uses an exponential backoff starting with an initial delay of 1000ms. * @param fn The function to be executed and retried on failure. * @param options Additional options which configure the retry behavior. * @returns The result of successfully executing `fn`. * @throws Rethrows the final error of running `fn` when the function stops retrying. */ export async function retry(fn, options = {}) { let { shouldRetry, getDelay, onError } = options; shouldRetry = shouldRetry ?? ((attempt)=>limitAttempts(attempt, 5)); getDelay = getDelay ?? ((attempt)=>getExponentialDelay(attempt, 1000)); let attempt = 0; let lastError = undefined; do { try { await delay(getDelay(attempt)); return await fn(); } catch (e) { onError?.(e, attempt); lastError = e; } }while (shouldRetry(attempt++)) // If we reach this fn errored and shouldn't retry anymore. Simply rethrow the final error as // a means of ending the retry process without a result. throw lastError; } function limitAttempts(attempt, maxAttempts) { return attempt <= maxAttempts; } function getExponentialDelay(attempt, startingDelay, initialDelay = false) { const exponent = initialDelay ? attempt + 1 : attempt; return startingDelay * Math.pow(2, exponent); } async function delay(ms) { if (ms <= 0) { return; } return new Promise((res)=>setTimeout(res, ms)); }