UNPKG

retry-ts

Version:

Retry combinators for monadic actions that may fail

155 lines (154 loc) 5.18 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; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.monoidRetryPolicy = exports.applyPolicy = exports.defaultRetryStatus = exports.exponentialBackoff = exports.capDelay = exports.constantDelay = exports.limitRetriesByDelay = exports.limitRetries = exports.Monoid = void 0; /** * @since 0.1.0 */ var M = __importStar(require("fp-ts/lib/Monoid")); var O = __importStar(require("fp-ts/lib/Option")); var Semigroup_1 = require("fp-ts/lib/Semigroup"); var Ord_1 = require("fp-ts/lib/Ord"); var pipeable_1 = require("fp-ts/lib/pipeable"); /** * 'RetryPolicy' is a 'Monoid'. You can collapse multiple strategies into one using 'concat'. * The semantics of this combination are as follows: * * 1. If either policy returns 'None', the combined policy returns * 'None'. This can be used to inhibit after a number of retries, * for example. * * 2. If both policies return a delay, the larger delay will be used. * This is quite natural when combining multiple policies to achieve a * certain effect. * * @example * import { monoidRetryPolicy, exponentialBackoff, limitRetries } from 'retry-ts' * * // One can easily define an exponential backoff policy with a limited * // number of retries: * export const limitedBackoff = monoidRetryPolicy.concat(exponentialBackoff(50), limitRetries(5)) * * @since 0.1.3 */ exports.Monoid = /*#__PURE__*/ M.getFunctionMonoid( /*#__PURE__*/ O.getApplyMonoid({ concat: /*#__PURE__*/ Semigroup_1.getJoinSemigroup(Ord_1.ordNumber).concat, empty: 0 }) /*#__PURE__*/ )(); /** * Retry immediately, but only up to `i` times. * * @since 0.1.0 */ function limitRetries(i) { return function (status) { return (status.iterNumber >= i ? O.none : O.some(0)); }; } exports.limitRetries = limitRetries; /** * Add an upperbound to a policy such that once the given time-delay * amount *per try* has been reached or exceeded, the policy will stop * retrying and fail. * * @since 0.1.0 */ function limitRetriesByDelay(maxDelay, policy) { return function (status) { return pipeable_1.pipe(status, policy, O.filter(function (delay) { return delay < maxDelay; })); }; } exports.limitRetriesByDelay = limitRetriesByDelay; /** * Constant delay with unlimited retries * * @since 0.1.0 */ function constantDelay(delay) { return function () { return O.some(delay); }; } exports.constantDelay = constantDelay; /** * Set a time-upperbound for any delays that may be directed by the * given policy. This function does not terminate the retrying. The policy * capDelay(maxDelay, exponentialBackoff(n))` will never stop retrying. It * will reach a state where it retries forever with a delay of `maxDelay` * between each one. To get termination you need to use one of the * 'limitRetries' function variants. * * @since 0.1.0 */ function capDelay(maxDelay, policy) { return function (status) { return pipeable_1.pipe(status, policy, O.map(function (delay) { return Math.min(maxDelay, delay); })); }; } exports.capDelay = capDelay; /** * Grow delay exponentially each iteration. * Each delay will increase by a factor of two. * * @since 0.1.0 */ function exponentialBackoff(delay) { return function (status) { return O.some(delay * Math.pow(2, status.iterNumber)); }; } exports.exponentialBackoff = exponentialBackoff; /** * Initial, default retry status. Exported mostly to allow user code * to test their handlers and retry policies. * * @since 0.1.0 */ exports.defaultRetryStatus = { iterNumber: 0, cumulativeDelay: 0, previousDelay: O.none }; /** * Apply policy on status to see what the decision would be. * * @since 0.1.0 */ function applyPolicy(policy, status) { var previousDelay = policy(status); return { iterNumber: status.iterNumber + 1, cumulativeDelay: status.cumulativeDelay + O.getOrElse(function () { return 0; })(previousDelay), previousDelay: previousDelay }; } exports.applyPolicy = applyPolicy; // ------------------------------------------------------------------------------------- // deprecated // ------------------------------------------------------------------------------------- /** * Use [`Monoid`](#monoid) instead. * @since 0.1.0 * @deprecated */ exports.monoidRetryPolicy = exports.Monoid;