@parzh/retryable
Version:
Convenience function to retry an action
166 lines • 6.04 kB
JavaScript
;
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