@augment-vir/common
Version:
A collection of augments, helpers types, functions, and classes for any JavaScript environment.
65 lines (64 loc) • 2.15 kB
JavaScript
import { ensureErrorAndPrependMessage, wait } from '@augment-vir/core';
/**
* Calls `callback` until it doesn't throw an error or throws an error when `maxRetries` is reached.
* Similar to the `waitUntil` guard from '@augment-vir/assert' but doesn't check the callback's
* output.
*
* @category Function
* @category Package : @augment-vir/common
* @example
*
* ```ts
* import {callWithRetries} from '@augment-vir/common';
*
* const result = callWithRetries(5, () => {
* if (Math.random() < 0.5) {
* return 'done';
* } else {
* throw new Error();
* }
* });
* ```
*
* @package [`@augment-vir/common`](https://www.npmjs.com/package/@augment-vir/common)
*/
export function retry(maxRetries, callback, options = {}) {
return internalRetry(0, maxRetries, callback, options);
}
function internalRetry(currentRetry, maxRetries, callback, options = {}) {
try {
const result = callback({
retryCount: currentRetry,
isFirstExecution: currentRetry === 0,
isFirstRetry: currentRetry === 1,
isLastRetry: currentRetry === maxRetries,
});
if (result instanceof Promise) {
return result.catch(async (error) => {
if (currentRetry >= maxRetries) {
throw ensureErrorAndPrependMessage(error, 'Retry max reached');
}
else {
if (options.interval) {
await wait(options.interval);
}
return internalRetry(currentRetry + 1, maxRetries, callback, options);
}
});
}
else {
return result;
}
}
catch (error) {
if (currentRetry >= maxRetries) {
throw ensureErrorAndPrependMessage(error, 'Retry max reached');
}
else if (options.interval) {
return wait(options.interval).then(() => internalRetry(currentRetry + 1, maxRetries, callback, options));
}
else {
return internalRetry(currentRetry + 1, maxRetries, callback, options);
}
}
}