retry-ts
Version:
Retry combinators for monadic actions that may fail
155 lines (154 loc) • 5.18 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;
};
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;
;