@newdash/newdash
Version:
javascript/typescript utility library
83 lines (82 loc) • 2.97 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.circuit = exports.TemporaryUnAvailableError = void 0;
/* eslint-disable max-len */
const assert_1 = require("../assert");
const cacheProvider_1 = require("../cacheProvider");
const functionWrapper_1 = require("../functional/functionWrapper");
const toHashCode_1 = require("../functional/toHashCode");
/**
* TemporaryUnAvailableError
*
* when the circuit breaker is open (failure happened latest), will direct throw this error
*
* @internal please do not throw this error outside of newdash inner functions
*/
class TemporaryUnAvailableError extends Error {
/**
* the error cause the function temporary not available
*/
causeError;
constructor(msg, causeError) {
if (causeError !== undefined) {
super(`${msg} cause error message(${causeError.message})`);
}
else {
super(msg);
}
this.causeError = causeError;
}
}
exports.TemporaryUnAvailableError = TemporaryUnAvailableError;
/**
*
* @ignore
* @private
* @internal
* @param error
* @param key
* @param breakerOpenTimers
* @param breakerOpenReason
*/
function errorWithCircuit(error, key, breakerOpenTimers, breakerOpenReason) {
if (!(error instanceof TemporaryUnAvailableError)) {
breakerOpenTimers.set(key, Date.now());
breakerOpenReason.set(key, error);
}
throw error;
}
/**
* fallback to circuit
*
* will directly raise error [[TemporaryUnAvailableError]] when some error happened before in duration
*
* @category Fallback
* @param runner
* @param openDuration default is 10000 (10 seconds)
* @param cacheSize the timer & error cache size, default is 1024
*/
function circuit(runner, openDuration = 10 * 1000, cacheSize = 1024) {
(0, assert_1.mustProvide)(runner, "runner", "function");
(0, assert_1.mustProvide)(openDuration, "openDuration", "number");
if (openDuration === 0) {
return runner;
}
const funcName = runner["name"] || "Unknown";
return (0, functionWrapper_1.createFunctionWrapper)(runner, {
global: {
breakerOpenTimers: new cacheProvider_1.LRUCacheProvider(cacheSize),
breakerOpenReason: new cacheProvider_1.LRUCacheProvider(cacheSize),
},
before: (ctx) => {
ctx.state.key = (0, toHashCode_1.toHashCode)(ctx.args);
const latestFailedTime = ctx.global.breakerOpenTimers.get(ctx.state.key) ?? 0;
const availableTime = latestFailedTime + openDuration;
if (availableTime > Date.now()) {
throw new TemporaryUnAvailableError(`function [${funcName}] is temporary un-available until ${availableTime}`, ctx.global.breakerOpenReason.get(ctx.state.key));
}
},
error: (ctx, error) => errorWithCircuit(error, ctx.state.key, ctx.global.breakerOpenTimers, ctx.global.breakerOpenReason),
});
}
exports.circuit = circuit;