UNPKG

@parzh/retryable

Version:

Convenience function to retry an action

166 lines 6.04 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); var assert_natural_impl_1 = __importDefault(require("./assert-natural.impl")); var assert_non_negative_impl_1 = __importDefault(require("./assert-non-negative.impl")); var delays_1 = __importStar(require("./delays")); /** @private */ var RETRY_COUNT_DEFAULT = 0; /** * Retry action * @param action Action to perform an retry if needed * @example * const content = await retryable((resolve, reject, retry) => { * fs.readfile("/path/to/file", (err, data) => { * if (!err) * return resolve(data); * * if (retry.count >= RETRY_LIMIT) * if (SHOULD_IGNORE_RETRY_LIMIT) * retry.setCount(0); * * else * return reject("Retry limit reached!"); * * if (SHOULD_RETRY_IMMEDIATELY) * retry(); * * else * retry.after("exponential"); * }); * }); */ function retryable(action) { var retryCount = { value: RETRY_COUNT_DEFAULT, next: null, updateValue: function () { if (retryCount.next != null) { retryCount.value = retryCount.next; retryCount.next = null; } else { retryCount.value += 1; } }, setNext: function (newNext) { if (newNext !== RETRY_COUNT_DEFAULT) assert_natural_impl_1.default(newNext, "new value of retry.count"); retryCount.next = newNext; }, /** @deprecated Use `retryCount.setNext(:number)` */ reset: function (count) { retryCount.setNext(count !== null && count !== void 0 ? count : RETRY_COUNT_DEFAULT); }, /** @namespace */ max: { value: Infinity, customized: false, onExceeded: null, get exceededMessage() { return "Retry limit exceeded after " + this.value + " retries (" + (this.value + 1) + " attempts total)"; }, }, }; var retryTimeoutId; var settled = false; return new Promise(function (res, rej) { var resolve = function () { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } settled = true; res.apply(void 0, args); }; var reject = function () { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } settled = true; rej.apply(void 0, args); }; var retry = Object.assign(function () { retryCount.updateValue(); if (retryCount.value > retryCount.max.value) if (retryCount.max.onExceeded != null) retryCount.max.onExceeded(); else return reject(retryCount.max.exceededMessage); if (settled) return; // explicitly relying on hoisting here // eslint-disable-next-line @typescript-eslint/no-use-before-define execute(); }, { count: retryCount.value, setCount: retryCount.setNext, setMaxCount: function (value, onExceeded) { // ignore subsequent calls if (retryCount.max.customized) return; assert_natural_impl_1.default(value, "max value of retry.count"); retryCount.max.value = value; retryCount.max.customized = true; if (onExceeded == null || onExceeded === "reject") return; if (onExceeded === "resolve") retryCount.max.onExceeded = resolve; else retryCount.max.onExceeded = onExceeded; }, after: function (delay) { var msec; if (delays_1.isNamed(delay)) msec = delays_1.default[delay](retryCount.value); else msec = +delay; assert_non_negative_impl_1.default(msec, "retry delay"); retryTimeoutId = setTimeout(retry, msec); }, cancel: function () { if (retryTimeoutId != null) clearTimeout(retryTimeoutId); }, }); Object.defineProperty(retry, "count", { get: function () { return retryCount.value; }, set: function () { return reject("Cannot set readonly `count`; use `retry.setCount()` instead"); }, }); function execute() { action(resolve, reject, retry, // arguments below are deprecated, // left for backwards compatibility retryCount.value, retryCount.reset); } execute(); }); } exports.default = retryable; //# sourceMappingURL=retryable.js.map