youtube-maze/lib/retry.mjs

65 lines
1.7 KiB
JavaScript
Raw Normal View History

2020-11-28 17:07:04 +00:00
import debug from 'debug';
import { sleep } from './util.mjs';
const log = debug('youtube-maze:retry');
/**
* An error that is expected to be temporary such that the initial action
* may be retried.
*/
export class TemporaryError extends Error
{
constructor(message)
{
super(message);
this.name = this.constructor.name;
Error.captureStackTrace(this, this.constructor);
}
}
/**
* Make an async function retry-able.
*
* When the underlying function throws a TemporaryError, the initial
* call will be repeated, under the limits set below.
*
* @param function func Async function to call.
* @param number retries Allowed number of retries before failing.
* @param number cooldown Time to wait before retrying (ms).
* @return function New function that is retryable.
*/
export const retryable = (func, retries = 3, cooldown = 1000) =>
{
return async (...args) =>
{
while (true)
{
let remRetries = retries;
let curCooldown = cooldown;
try
{
const result = await func(...args);
return result;
}
catch (err)
{
if (err instanceof TemporaryError && remRetries > 0)
{
log(`\
${func.name}(${args}) failed with error "${err.message}"
Retrying in ${curCooldown} ms (${remRetries} retries remaining)`);
await sleep(curCooldown);
remRetries -= 1;
curCooldown *= 2;
}
else
{
throw err;
}
}
}
};
};