mollitia
Version:
JavaScript Resilience Library
2 lines (1 loc) • 25 kB
JavaScript
"use strict";var M=Object.defineProperty;var _=(l,r,e)=>r in l?M(l,r,{enumerable:!0,configurable:!0,writable:!0,value:e}):l[r]=e;var i=(l,r,e)=>(_(l,typeof r!="symbol"?r+"":r,e),e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const p=[],k=l=>{p.push(l)};class E{}class B{constructor(r,e,t){i(this,"listeners");i(this,"eventName");i(this,"index");this.listeners=r,this.eventName=e,this.index=t}dispose(){this.listeners[this.eventName].splice(this.index,1)}}class I{constructor(){i(this,"listeners");this.listeners={}}on(r,e){this.listeners[r]=this.listeners[r]||[];const t=this.listeners[r].push(e);return new B(this.listeners,r,t-1)}off(r,e){const t=this.listeners[r];if(t){for(let s=t.length-1;s>0;s--)if(t[s]===e){t.splice(s,1);break}}}emit(r,...e){const t=this.listeners[r];return t?(t.forEach(s=>{s(...e)}),!0):!1}dispose(){this.listeners={}}}class w extends Error{constructor(){super("Circuit has no function set"),Object.setPrototypeOf(this,w.prototype)}}class F{constructor(){i(this,"modules")}}class z{constructor(){i(this,"name");i(this,"func");i(this,"options")}}const H=async()=>Promise.reject(new w),q=[];class N extends I{constructor(e){var t;super();i(this,"name");i(this,"func");i(this,"modules");this.name=e!=null&&e.name?e.name:`Circuit${q.length}`;for(const s of p)s.onCircuitCreate&&s.onCircuitCreate(this,e==null?void 0:e.options);this.func=e!=null&&e.func?e.func:H,this.modules=((t=e==null?void 0:e.options)==null?void 0:t.modules)||[],q.push(this)}get activeModules(){return this.modules.filter(e=>e.active)}fn(e){return this.func=e,this}async execute(...e){let t;if(this.activeModules.length)if(this.activeModules.length>1){const s=[];for(let a=2;a<this.activeModules.length;a++)s.push(this,this.activeModules[a].execute.bind(this.activeModules[a]));s.push(this,this.func,...e),t=this.activeModules[0].execute(this,this.activeModules[1].execute.bind(this.activeModules[1]),...s)}else t=this.activeModules[0].execute(this,this.func,...e);else t=this.func(...e);return this.emit("execute",this,t,e),t}dispose(){super.dispose(),this.modules&&this.modules.forEach(e=>e.dispose())}}class g{constructor(){i(this,"name");i(this,"active");i(this,"logger")}}const b=[];class f extends I{constructor(e){super();i(this,"name");i(this,"active");i(this,"logger");this.active=(e==null?void 0:e.active)!==void 0?e.active:!0,this.name=(e==null?void 0:e.name)!==void 0?e.name:`Module${b.length}`;for(const t of p)t.onModuleCreate&&t.onModuleCreate(this,e);this.logger=e==null?void 0:e.logger,b.push(this)}execute(e,t,...s){const a=t(...s),h=this.getExecParams(e,s);return this.emit("execute",e,a,h),a}getExecParams(e,t){const s=e.modules.findIndex(h=>h===this),a=t.length-(e.modules.length-1-s)*2;return t.filter((h,n)=>t.length-n<=a)}}class A extends g{constructor(){super(...arguments);i(this,"delay")}}class C extends Error{constructor(){super("Timed out"),Object.setPrototypeOf(this,C.prototype)}}class W extends f{constructor(e){super(e);i(this,"delay");this.delay=(e==null?void 0:e.delay)!==void 0?e.delay:6e4}async execute(e,t,...s){const a=this._promiseTimeout(e,this.delay,t,...s),h=this.getExecParams(e,s);return this.emit("execute",e,a,h),a}async _promiseTimeout(e,t,s,...a){let h;return t!==0&&t!==1/0?Promise.race([s(...a),new Promise((n,u)=>{h=setTimeout(()=>{this.emitTimeout(e),u(new C)},t)})]).then(n=>(clearTimeout(h),n)).catch(n=>(clearTimeout(h),Promise.reject(n))):s(...a)}emitTimeout(e){var t;(t=this.logger)==null||t.debug(`${e.name}/${this.name} - Has timed out`),this.emit("timeout",e)}}async function j(l=1){return new Promise(r=>{setTimeout(()=>{r()},l)})}var D=(l=>(l.CONSTANT="constant",l.LINEAR="linear",l.EXPONENTIAL="exponential",l.JITTER="jitter",l))(D||{});class $ extends g{constructor(){super(...arguments);i(this,"attempts");i(this,"interval");i(this,"mode");i(this,"factor");i(this,"maxInterval");i(this,"fastFirst");i(this,"jitterAdjustment");i(this,"onRejection")}}class L extends f{constructor(e){super(e);i(this,"attempts");i(this,"interval");i(this,"mode");i(this,"factor");i(this,"maxInterval");i(this,"fastFirst");i(this,"_jitterAdjustment");i(this,"onRejection");this.attempts=(e==null?void 0:e.attempts)??2,this.interval=(e==null?void 0:e.interval)??0,this.fastFirst=(e==null?void 0:e.fastFirst)??!1,this.maxInterval=(e==null?void 0:e.maxInterval)??1/0,this.mode=(e==null?void 0:e.mode)??"constant",this._jitterAdjustment=this.adjustJitterValue((e==null?void 0:e.jitterAdjustment)??.1);const t=this.mode==="linear"?1:2;this.factor=(e==null?void 0:e.factor)??t,this.onRejection=(e==null?void 0:e.onRejection)||(()=>!0)}get jitterAdjustment(){return this._jitterAdjustment}set jitterAdjustment(e){this._jitterAdjustment=this.adjustJitterValue(e)}adjustJitterValue(e){return Math.min(1,Math.max(0,e))}async execute(e,t,...s){const a=this._promiseRetry(e,this.attempts+1,t,...s),h=this.getExecParams(e,s);return this.emit("execute",e,a,h),a}async waitBeforeNextTry(e,t){let s=0;if(this.fastFirst){if(e===0)return this.emit("delay-before-next-retry",t,0),Promise.resolve();e--}switch(this.mode){case"linear":{s=Math.min(this.interval+this.interval*this.factor*e,this.maxInterval);break}case"exponential":{s=Math.min(this.interval*this.factor**e,this.maxInterval);break}case"jitter":{const a=Math.min(this.interval*this.factor**e,this.maxInterval),h=a*(1-this.jitterAdjustment),u=Math.min(a*(1+this.jitterAdjustment),this.maxInterval)-h;s=Math.floor(Math.random()*u)+h;break}case"constant":default:{s=Math.min(this.interval,this.maxInterval);break}}return this.emit("delay-before-next-retry",t,s),j(s)}async _promiseRetry(e,t,s,...a){var h,n;return t-1===0?(this.attempts&&(this.emit("retry",e,this.attempts),(h=this.logger)==null||h.debug(`${e.name}/${this.name} - Retry: (${this.attempts}/${this.attempts})`)),s(...a).then(u=>(this.attempts>0?this.emit("success-with-retry",e,this.attempts):this.emit("success-without-retry",e),u)).catch(u=>{throw this.attempts>0?this.emit("failure-with-retry",e,this.attempts):this.emit("failure-without-retry",e),u})):(t!==this.attempts+1&&(this.emit("retry",e,this.attempts-t+1),(n=this.logger)==null||n.debug(`${e.name}/${this.name} - Retry: (${this.attempts-t+1}/${this.attempts})`)),s(...a).then(u=>(t!==this.attempts+1?this.emit("success-with-retry",e,this.attempts-t+1):this.emit("success-without-retry",e),u)).catch(async u=>{const c=this.onRejection(u,this.attempts-t+1);return c===!1?(t!==this.attempts+1?this.emit("failure-with-retry",e,this.attempts-t+1):this.emit("failure-without-retry",e),Promise.reject(u)):(typeof c=="number"?(this.emit("delay-before-next-retry",e,c),await j(c)):await this.waitBeforeNextTry(this.attempts-t+1,e),this._promiseRetry(e,t-1,s,...a))}))}}class V extends g{constructor(){super(...arguments);i(this,"callback",e=>e)}}class U extends f{constructor(e){super(e);i(this,"callback");this.callback=(e==null?void 0:e.callback)||(t=>t)}async execute(e,t,...s){const a=this._promiseFallback(e,t,...s),h=this.getExecParams(e,s);return this.emit("execute",e,a,h),a}async _promiseFallback(e,t,...s){return new Promise((a,h)=>{t(...s).then(n=>{a(n)}).catch(n=>{h(this.callback(n))})})}}class Q{constructor(r,e){i(this,"ttl");i(this,"res");this.ttl=r,this.res=e}}class J{constructor(){i(this,"map");this.map=new Map}set(r,...e){this._setLoopMap(this.map,r,...e)}get(...r){return this._getLoopMap(this.map,...r)}clear(){return this._clearLoopMap(this.map)}_setLoopMap(r,e,...t){if(t.length===2){const s={map:new Map,cache:new Q(Date.now()+e,t[1])};r.set(t[0],s)}else if(r.get(t[0])){const s=t.splice(0,1)[0];this._setLoopMap(r.get(s).map,e,...t)}else{const s=new Map;r.set(t[0],{map:s}),t.splice(0,1),this._setLoopMap(s,e,...t)}}_getLoopMap(r,...e){if(r){if(e.length===1)return r.get(e[0])&&r.get(e[0]).cache;{const t=e.splice(0,1)[0];return r.get(t)?this._getLoopMap(r.get(t).map,...e):null}}else return null}_clearLoopMap(r){let e=!1;return r.forEach(t=>{t.map&&this._clearLoopMap(t.map)===!0&&(e=!0),t.cache&&Date.now()>t.cache.ttl&&(delete t.cache,e=!0)}),e}}class X extends g{constructor(){super(...arguments);i(this,"ttl");i(this,"cacheClearInterval");i(this,"getInformationFromCache");i(this,"adjustCacheParams")}}class K extends f{constructor(e){super(e);i(this,"ttl");i(this,"getInformationFromCache");i(this,"adjustCacheParams");i(this,"cache");i(this,"_cacheClearInterval");i(this,"_cacheInterval");this.ttl=(e==null?void 0:e.ttl)!==void 0?e.ttl:6e3,this.getInformationFromCache=(e==null?void 0:e.getInformationFromCache)!==void 0?e.getInformationFromCache:!1,this.adjustCacheParams=(e==null?void 0:e.adjustCacheParams)||null,this._cacheInterval=null,this._cacheClearInterval=0,this.cacheClearInterval=(e==null?void 0:e.cacheClearInterval)!==void 0?e.cacheClearInterval:9e5,this.cache=new J}get cacheClearInterval(){return this._cacheClearInterval}set cacheClearInterval(e){this._cacheClearInterval=e,this._initializeInterval()}async execute(e,t,...s){const a=this._promiseCache(e,t,...s),h=this.getExecParams(e,s);return this.emit("execute",e,a,h),a}dispose(){super.dispose(),this._cacheInterval&&(clearTimeout(this._cacheInterval),this._cacheInterval=null)}async _promiseCache(e,t,...s){return new Promise((a,h)=>{var x;const n=this.getExecParams(e,s);let u=n;this.adjustCacheParams&&(u=this.adjustCacheParams(e.func,...n));const c=this.cache.get(e.func,...u);if(c){typeof c.res=="object"&&this.getInformationFromCache&&(c.res._mollitiaIsFromCache=!0);const m=Date.now();this.ttl!==1/0&&c.ttl<m?t(...s).then(d=>{this.ttl>0&&this.cache.set(this.ttl,e.func,...u,d),typeof d=="object"&&this.getInformationFromCache&&(d._mollitiaIsFromCache=!1),a(d)}).catch(()=>{var d;(d=this.logger)==null||d.debug(`${e.name}/${this.name} - Cache: Hit [Old]`),this.emit("cache-hit-old",e,u),a(c.res)}):((x=this.logger)==null||x.debug(`${e.name}/${this.name} - Cache: Hit`),this.emit("cache-hit",e,u),a(c.res))}else t(...s).then(m=>{this.ttl>0&&this.cache.set(this.ttl,e.func,...u,m),typeof m=="object"&&this.getInformationFromCache&&(m._mollitiaIsFromCache=!1),a(m)}).catch(m=>{h(m)})})}_initializeInterval(){this._cacheInterval&&(clearTimeout(this._cacheInterval),this._cacheInterval=null),this.cacheClearInterval!==0&&this.cacheClearInterval!==1/0&&(this._cacheInterval=setTimeout(()=>{var t;this.cache.clear()&&((t=this.logger)==null||t.debug(`${this.name} - Cache: Clear`)),this._initializeInterval()},this.cacheClearInterval))}}const G=2147483647;class Y extends g{constructor(){super(...arguments);i(this,"concurrentSize");i(this,"queueSize");i(this,"maxQueueWait")}}class y extends Error{constructor(){super("Circuit is overloaded"),Object.setPrototypeOf(this,y.prototype)}}class S extends Error{constructor(){super("Waiting for too long in queue"),Object.setPrototypeOf(this,S.prototype)}}class Z extends I{constructor(e,...t){super();i(this,"promise");i(this,"params");this.promise=e,this.params=t}async execute(){return new Promise((e,t)=>{this.emit("execute"),this.promise(...this.params).then(s=>{this.emit("resolve",s),e(s)}).catch(s=>{this.emit("reject",s),t(s)})})}}class ee extends f{constructor(e){super(e);i(this,"concurrentSize");i(this,"queueSize");i(this,"maxQueueWait");i(this,"concurrentBuffer");i(this,"queueBuffer");this.concurrentSize=(e==null?void 0:e.concurrentSize)!==void 0?e.concurrentSize:10,this.queueSize=(e==null?void 0:e.queueSize)!==void 0?e.queueSize:10,this.maxQueueWait=(e==null?void 0:e.maxQueueWait)!==void 0?e.maxQueueWait:6e4,this.concurrentBuffer=[],this.queueBuffer=[]}async execute(e,t,...s){const a=this._promiseBulkhead(e,t,...s),h=this.getExecParams(e,s);return this.emit("execute",e,a,h),a}async _promiseBulkhead(e,t,...s){return new Promise((a,h)=>{const n=new Z(t,...s);if(this.concurrentBuffer.length<this.concurrentSize)n.execute().then(u=>{a(u)}).catch(u=>{h(u)}).finally(()=>{this.concurrentBuffer.splice(this.concurrentBuffer.indexOf(n),1),this.emit("update-concurrent-buffer",e,this.concurrentBuffer),this._addBufferedPromise(e)}),this.concurrentBuffer.push(n),this.emit("update-concurrent-buffer",e,this.concurrentBuffer);else if(this.queueBuffer.length<this.queueSize){this.queueBuffer.push(n),this.emit("update-queue-buffer",e,this.queueBuffer);let u;this.maxQueueWait<=G&&(u=setTimeout(()=>{this.queueBuffer.splice(this.queueBuffer.indexOf(n),1),this.emit("update-queue-buffer",e,this.queueBuffer),x.dispose(),m.dispose(),h(new S)},this.maxQueueWait));const c=n.on("execute",()=>{c.dispose(),clearTimeout(u)}),x=n.on("resolve",d=>{clearTimeout(u),this.concurrentBuffer.splice(this.concurrentBuffer.indexOf(n),1),this.emit("update-concurrent-buffer",e,this.concurrentBuffer),x.dispose(),m.dispose(),this._addBufferedPromise(e),a(d)}),m=n.on("reject",d=>{clearTimeout(u),this.concurrentBuffer.splice(this.concurrentBuffer.indexOf(n),1),this.emit("update-concurrent-buffer",e,this.concurrentBuffer),x.dispose(),m.dispose(),this._addBufferedPromise(e),h(d)})}else h(new y)})}_addBufferedPromise(e){if(this.queueBuffer.length>0){const t=this.queueBuffer.splice(0,1)[0];this.emit("update-queue-buffer",e,this.queueBuffer),t.execute().catch(()=>{}),this.concurrentBuffer.push(t),this.emit("update-concurrent-buffer",e,this.concurrentBuffer)}}}class O extends Error{constructor(e,t){super("Ratelimited");i(this,"remainingTimeInRatelimit");this.name=t,this.remainingTimeInRatelimit=e,Object.setPrototypeOf(this,O.prototype)}}class te extends f{constructor(e){super(e);i(this,"limitPeriod");i(this,"limitForPeriod");i(this,"requestsTime");this.limitPeriod=(e==null?void 0:e.limitPeriod)!==void 0?e.limitPeriod:0,this.limitForPeriod=(e==null?void 0:e.limitForPeriod)!==void 0?e.limitForPeriod:1/0,this.requestsTime=[]}async getState(){return new Promise(e=>{e({requests:this.requestsTime})})}async setState(e,t){return new Promise(s=>{s()})}async clearState(){return new Promise(e=>{this.requestsTime=[],e()})}async execute(e,t,...s){var u;let a;try{a=await this.getState()}catch(c){(u=this.logger)==null||u.warn(c)}a!=null&&a.requests&&(this.requestsTime=a==null?void 0:a.requests);const h=this._promiseRatelimit(e,t,...s),n=this.getExecParams(e,s);return this.emit("execute",e,h,n),h}async addCurrentRequest(e){var t;this.requestsTime.push(e);try{await this.setState([{key:"requests",value:this.requestsTime}],this.limitPeriod)}catch(s){(t=this.logger)==null||t.warn(s)}}async _promiseRatelimit(e,t,...s){var h;if(!this.limitPeriod)return t(...s);const a=new Date().getTime();if(this.requestsTime.length<this.limitForPeriod)return await this.addCurrentRequest(a),t(...s);{const n=a-this.requestsTime[0];return n>this.limitPeriod?(this.requestsTime.splice(0,1),await this.addCurrentRequest(a),t(...s)):((h=this.logger)==null||h.debug(`${e.name}/${this.name} - Ratelimited`),this.emit("ratelimit",e),Promise.reject(new O(this.limitPeriod-n,this.name)))}}}class T extends Error{constructor(){super("Circuit is opened"),Object.setPrototypeOf(this,T.prototype)}}class v extends Error{constructor(){super("Max allowed requests reached"),Object.setPrototypeOf(this,v.prototype)}}var P=(l=>(l.CLOSED="closed",l.HALF_OPENED="half-opened",l.OPENED="opened",l))(P||{});class se extends g{constructor(){super(...arguments);i(this,"state");i(this,"openStateDelay");i(this,"halfOpenStateMaxDelay");i(this,"slidingWindowSize");i(this,"minimumNumberOfCalls");i(this,"failureRateThreshold");i(this,"slowCallRateThreshold");i(this,"slowCallDurationThreshold");i(this,"permittedNumberOfCallsInHalfOpenState");i(this,"onError")}}var o=(l=>(l[l.SUCCESS=0]="SUCCESS",l[l.FAILURE=1]="FAILURE",l[l.TIMEOUT=2]="TIMEOUT",l))(o||{});class R extends f{constructor(e){super(e);i(this,"state");i(this,"stateTimestamp");i(this,"openStateDelay");i(this,"halfOpenStateMaxDelay");i(this,"slidingWindowSize");i(this,"minimumNumberOfCalls");i(this,"failureRateThreshold");i(this,"slowCallRateThreshold");i(this,"slowCallDurationThreshold");i(this,"permittedNumberOfCallsInHalfOpenState");i(this,"onError");i(this,"halfOpenMaxDelayTimeout",0);i(this,"openTimeout",0);i(this,"nbRequestsInHalfOpenedState");i(this,"requests");i(this,"isInitialized",!1);this.state=(e==null?void 0:e.state)!==void 0?e.state:"closed",this.stateTimestamp=Date.now(),this.openStateDelay=(e==null?void 0:e.openStateDelay)!==void 0?e.openStateDelay:60*1e3,this.halfOpenStateMaxDelay=(e==null?void 0:e.halfOpenStateMaxDelay)!==void 0?e.halfOpenStateMaxDelay:0,this.slidingWindowSize=(e==null?void 0:e.slidingWindowSize)!==void 0?e.slidingWindowSize:10,this.minimumNumberOfCalls=(e==null?void 0:e.minimumNumberOfCalls)!==void 0?e.minimumNumberOfCalls:10,this.failureRateThreshold=(e==null?void 0:e.failureRateThreshold)!==void 0?e.failureRateThreshold:50,this.slowCallDurationThreshold=(e==null?void 0:e.slowCallDurationThreshold)!==void 0?e.slowCallDurationThreshold:6e4,this.slowCallRateThreshold=(e==null?void 0:e.slowCallRateThreshold)!==void 0?e==null?void 0:e.slowCallRateThreshold:100,this.permittedNumberOfCallsInHalfOpenState=(e==null?void 0:e.permittedNumberOfCallsInHalfOpenState)!==void 0?e.permittedNumberOfCallsInHalfOpenState:2,this.nbRequestsInHalfOpenedState=0,this.requests=[],this.onError=(e==null?void 0:e.onError)||(()=>!0)}reinitializeCounters(){this.nbRequestsInHalfOpenedState=0,this.requests=[]}onOpened(){this.reinitializeCounters()}onClosed(){this.reinitializeCounters()}onHalfOpened(){this.reinitializeCounters()}isSomeEnum(e,t){return Object.values(e).includes(t)}isValidTimestamp(e){return!("timestamp"in e)||"timestamp"in e&&typeof e.timestamp=="number"}isValidState(e){return!!(e&&typeof e=="object"&&"state"in e&&this.isSomeEnum(P,e.state)&&this.isValidTimestamp(e))}isValidRequest(e){return!!(e&&typeof e=="object"&&"result"in e&&this.isSomeEnum(o,e.result)&&this.isValidTimestamp(e))}isValidData(e){return(!e.state||this.isValidState(e.state))&&(!e.requests||Array.isArray(e.requests)&&!e.requests.some(t=>!this.isValidRequest(t)))}async execute(e,t,...s){var n;try{const u=await this.getState();this.isValidData(u)&&(this.requests=u.requests?u.requests.map(c=>c.timestamp?{result:c.result,timestamp:c.timestamp}:{result:c.result}):[],u.state&&(this.state=u.state.state,this.stateTimestamp=u.state.timestamp))}catch(u){(n=this.logger)==null||n.warn(u)}this.isInitialized||(this.isInitialized=!0,this.state==="opened"?await this.setHalfDelay():this.state==="half-opened"&&await this.setOpenDelay());const a=this._promiseBreaker(e,t,...s),h=this.getExecParams(e,s);return this.emit("execute",e,a,h),a}async _promiseBreaker(e,t,...s){var a;switch(this.state){case"opened":return(a=this.logger)==null||a.debug(`${e.name}/${this.name} - Circuit is opened`),Promise.reject(new T);case"half-opened":return this.executeInHalfOpened(t,...s);case"closed":default:return this.executeInClosed(t,...s)}}adjustRequestResult(e,t){return!t&&e===1?0:e}async setStateSecure(e,t){var s;try{await this.setState(e,t)}catch(a){(s=this.logger)==null||s.warn(a)}}async executeInHalfOpened(e,...t){if(this.nbRequestsInHalfOpenedState<this.permittedNumberOfCallsInHalfOpenState){this.nbRequestsInHalfOpenedState++;const{requestResult:s,response:a,shouldReportFailure:h}=await this.executePromise(e,...t);return this.requests.push({result:this.adjustRequestResult(s,h)}),await this.setStateSecure([{key:"requests",value:this.requests}]),this.requests.length==this.permittedNumberOfCallsInHalfOpenState&&this.checkCallRatesHalfOpen(this.open.bind(this),this.close.bind(this)),s===1?Promise.reject(a):Promise.resolve(a)}else return Promise.reject(new v)}executePromise(e,...t){const s=new Date().getTime();return e(...t).then(a=>{const h=new Date().getTime();let n=0;return this.slowCallDurationThreshold!==0&&this.slowCallDurationThreshold!==1/0&&h-s>this.slowCallDurationThreshold&&(n=2),{requestResult:n,response:a,shouldReportFailure:!1}}).catch(a=>({requestResult:1,response:a,shouldReportFailure:this.onError(a)}))}checkCallRatesHalfOpen(e,t){const{nbSlow:s,nbFailure:a}=this.requests.reduce(this.getNbSlowAndFailure,{nbSlow:0,nbFailure:0});this.checkResult(s,a,this.requests.length)?t&&t():e()}checkResult(e,t,s){return!(this.slowCallRateThreshold<100&&e/s*100>=this.slowCallRateThreshold||this.failureRateThreshold<100&&t/s*100>=this.failureRateThreshold)}getNbSlowAndFailure(e,t){switch(t.result){case 1:e.nbFailure++;break;case 2:e.nbSlow++}return e}checkCallRatesClosed(){const{nbSlow:e,nbFailure:t}=this.requests.reduce(this.getNbSlowAndFailure,{nbSlow:0,nbFailure:0});return this.checkResult(e,t,this.requests.length)}async open(){this.state!=="opened"&&(this.clearHalfOpenTimeout(),this.state="opened",this.stateTimestamp=Date.now(),this.setHalfDelay(),this.onOpened(),await this.setStateSecure([{key:"state",value:{state:"opened",timestamp:Date.now()}},{key:"requests",value:""}]),this.emit("state-changed",this.state))}async halfOpen(){this.state!=="half-opened"&&(this.clearHalfOpenTimeout(),this.state="half-opened",this.stateTimestamp=Date.now(),this.setOpenDelay(),this.onHalfOpened(),await this.setStateSecure([{key:"state",value:{state:"half-opened",timestamp:Date.now()}},{key:"requests",value:""}]),this.emit("state-changed",this.state))}async close(){this.state!=="closed"&&(this.clearHalfOpenTimeout(),this.state="closed",this.stateTimestamp=Date.now(),this.onClosed(),await this.setStateSecure([{key:"state",value:{state:"closed",timestamp:Date.now()}},{key:"requests",value:""}]),this.emit("state-changed",this.state))}async setHalfDelay(){var t;const e=Date.now()-this.stateTimestamp;e>=this.openStateDelay?((t=this.logger)==null||t.debug(`${this.name} - Breaker: Half Open`),await this.halfOpen()):this.openTimeout=setTimeout(async()=>{var s;(s=this.logger)==null||s.debug(`${this.name} - Breaker: Half Open`),await this.halfOpen()},this.openStateDelay-e)}async setOpenDelay(){if(this.halfOpenStateMaxDelay){const e=Date.now()-this.stateTimestamp;e>=this.halfOpenStateMaxDelay?(this.halfOpenMaxDelayTimeout=0,await this.open()):this.halfOpenMaxDelayTimeout=setTimeout(async()=>{this.halfOpenMaxDelayTimeout=0,await this.open()},this.halfOpenStateMaxDelay-e)}}clearHalfOpenTimeout(){this.halfOpenMaxDelayTimeout&&(clearTimeout(this.halfOpenMaxDelayTimeout),this.halfOpenMaxDelayTimeout=0)}dispose(){super.dispose(),this.clearHalfOpenTimeout(),this.openTimeout&&(clearTimeout(this.openTimeout),this.openTimeout=0)}async getState(){return new Promise(e=>{e({requests:this.requests,state:{state:this.state,timestamp:this.stateTimestamp}})})}async setState(e,t){return new Promise(s=>{s()})}async clearState(){return new Promise(e=>{this.requests=[],e()})}}class ie extends R{constructor(r){super(r),this.slidingWindowSize=(r==null?void 0:r.slidingWindowSize)!==void 0?r.slidingWindowSize:10,this.slidingWindowSize<this.minimumNumberOfCalls&&(this.slidingWindowSize=this.minimumNumberOfCalls)}async executeInClosed(r,...e){const{requestResult:t,response:s,shouldReportFailure:a}=await this.executePromise(r,...e),h=this.adjustRequestResult(t,a);this.requests.push({result:h});const n=this.requests.length;let u=!1;return n>=this.minimumNumberOfCalls&&(n>this.slidingWindowSize&&(this.requests.splice(0,n-this.slidingWindowSize),u=!0,await this.setStateSecure([{key:"requests",value:this.requests}])),h!==o.SUCCESS&&(this.checkCallRatesClosed()||(await this.open(),u=!0))),u||await this.setStateSecure([{key:"requests",value:this.requests}]),t===o.FAILURE?Promise.reject(s):Promise.resolve(s)}}class ae extends R{constructor(e){super(e);i(this,"maxSize");this.slidingWindowSize=(e==null?void 0:e.slidingWindowSize)!==void 0?e.slidingWindowSize:60,this.maxSize=1e3}filterCalls(){let e=this.requests.length;e>=this.maxSize&&(this.requests.splice(0,1),e--);let t=!0;const s=new Date().getTime();for(let a=0;a<e&&t;a++)s-this.requests[0].timestamp>this.slidingWindowSize?this.requests.splice(0,1):t=!1}async executeInClosed(e,...t){const{requestResult:s,response:a,shouldReportFailure:h}=await this.executePromise(e,...t);this.filterCalls();const n=this.adjustRequestResult(s,h);this.requests.push({result:n,timestamp:new Date().getTime()});let u=!1;return this.requests.length>=this.minimumNumberOfCalls&&n!==o.SUCCESS&&(this.checkCallRatesClosed()||(await this.open(),u=!0)),u||await this.setStateSecure([{key:"requests",value:this.requests}],this.slidingWindowSize),s===o.FAILURE?Promise.reject(a):Promise.resolve(a)}}const re="0.1.1";exports.Addon=E;exports.BreakerError=T;exports.BreakerMaxAllowedRequestError=v;exports.BreakerState=P;exports.Bulkhead=ee;exports.BulkheadOptions=Y;exports.BulkheadOverloadError=y;exports.BulkheadQueueWaitError=S;exports.Cache=K;exports.CacheOptions=X;exports.Circuit=N;exports.CircuitFactory=z;exports.CircuitOptions=F;exports.Fallback=U;exports.FallbackOptions=V;exports.Module=f;exports.ModuleOptions=g;exports.NoFuncError=w;exports.Ratelimit=te;exports.RatelimitError=O;exports.Retry=L;exports.RetryMode=D;exports.RetryOptions=$;exports.SlidingCountBreaker=ie;exports.SlidingTimeBreaker=ae;exports.SlidingWindowBreaker=R;exports.SlidingWindowBreakerOptions=se;exports.SlidingWindowRequestResult=o;exports.Timeout=W;exports.TimeoutError=C;exports.TimeoutOptions=A;exports.circuits=q;exports.modules=b;exports.use=k;exports.version=re;