mollitia
Version:
JavaScript Resilience Library
2 lines (1 loc) • 25 kB
JavaScript
(function(n,d){typeof exports=="object"&&typeof module<"u"?d(exports):typeof define=="function"&&define.amd?define(["exports"],d):(n=typeof globalThis<"u"?globalThis:n||self,d(n.Mollitia={}))})(this,function(n){"use strict";var re=Object.defineProperty;var le=(n,d,w)=>d in n?re(n,d,{enumerable:!0,configurable:!0,writable:!0,value:w}):n[d]=w;var i=(n,d,w)=>(le(n,typeof d!="symbol"?d+"":d,w),w);const d=[],w=h=>{d.push(h)};class k{}class E{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 P{constructor(){i(this,"listeners");this.listeners={}}on(r,e){this.listeners[r]=this.listeners[r]||[];const t=this.listeners[r].push(e);return new E(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 O extends Error{constructor(){super("Circuit has no function set"),Object.setPrototypeOf(this,O.prototype)}}class B{constructor(){i(this,"modules")}}class F{constructor(){i(this,"name");i(this,"func");i(this,"options")}}const z=async()=>Promise.reject(new O),R=[];class H extends P{constructor(e){var t;super();i(this,"name");i(this,"func");i(this,"modules");this.name=e!=null&&e.name?e.name:`Circuit${R.length}`;for(const s of d)s.onCircuitCreate&&s.onCircuitCreate(this,e==null?void 0:e.options);this.func=e!=null&&e.func?e.func:z,this.modules=((t=e==null?void 0:e.options)==null?void 0:t.modules)||[],R.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 C{constructor(){i(this,"name");i(this,"active");i(this,"logger")}}const j=[];class g extends P{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${j.length}`;for(const t of d)t.onModuleCreate&&t.onModuleCreate(this,e);this.logger=e==null?void 0:e.logger,j.push(this)}execute(e,t,...s){const a=t(...s),l=this.getExecParams(e,s);return this.emit("execute",e,a,l),a}getExecParams(e,t){const s=e.modules.findIndex(l=>l===this),a=t.length-(e.modules.length-1-s)*2;return t.filter((l,c)=>t.length-c<=a)}}class N extends C{constructor(){super(...arguments);i(this,"delay")}}class T extends Error{constructor(){super("Timed out"),Object.setPrototypeOf(this,T.prototype)}}class A extends g{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),l=this.getExecParams(e,s);return this.emit("execute",e,a,l),a}async _promiseTimeout(e,t,s,...a){let l;return t!==0&&t!==1/0?Promise.race([s(...a),new Promise((c,u)=>{l=setTimeout(()=>{this.emitTimeout(e),u(new T)},t)})]).then(c=>(clearTimeout(l),c)).catch(c=>(clearTimeout(l),Promise.reject(c))):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 p(h=1){return new Promise(r=>{setTimeout(()=>{r()},h)})}var _=(h=>(h.CONSTANT="constant",h.LINEAR="linear",h.EXPONENTIAL="exponential",h.JITTER="jitter",h))(_||{});class W extends C{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 $ extends g{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),l=this.getExecParams(e,s);return this.emit("execute",e,a,l),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),l=a*(1-this.jitterAdjustment),u=Math.min(a*(1+this.jitterAdjustment),this.maxInterval)-l;s=Math.floor(Math.random()*u)+l;break}case"constant":default:{s=Math.min(this.interval,this.maxInterval);break}}return this.emit("delay-before-next-retry",t,s),p(s)}async _promiseRetry(e,t,s,...a){var l,c;return t-1===0?(this.attempts&&(this.emit("retry",e,this.attempts),(l=this.logger)==null||l.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),(c=this.logger)==null||c.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 m=this.onRejection(u,this.attempts-t+1);return m===!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 m=="number"?(this.emit("delay-before-next-retry",e,m),await p(m)):await this.waitBeforeNextTry(this.attempts-t+1,e),this._promiseRetry(e,t-1,s,...a))}))}}class L extends C{constructor(){super(...arguments);i(this,"callback",e=>e)}}class V extends g{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),l=this.getExecParams(e,s);return this.emit("execute",e,a,l),a}async _promiseFallback(e,t,...s){return new Promise((a,l)=>{t(...s).then(c=>{a(c)}).catch(c=>{l(this.callback(c))})})}}class U{constructor(r,e){i(this,"ttl");i(this,"res");this.ttl=r,this.res=e}}class Q{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 U(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 J extends C{constructor(){super(...arguments);i(this,"ttl");i(this,"cacheClearInterval");i(this,"getInformationFromCache");i(this,"adjustCacheParams")}}class X extends g{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 Q}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),l=this.getExecParams(e,s);return this.emit("execute",e,a,l),a}dispose(){super.dispose(),this._cacheInterval&&(clearTimeout(this._cacheInterval),this._cacheInterval=null)}async _promiseCache(e,t,...s){return new Promise((a,l)=>{var S;const c=this.getExecParams(e,s);let u=c;this.adjustCacheParams&&(u=this.adjustCacheParams(e.func,...c));const m=this.cache.get(e.func,...u);if(m){typeof m.res=="object"&&this.getInformationFromCache&&(m.res._mollitiaIsFromCache=!0);const f=Date.now();this.ttl!==1/0&&m.ttl<f?t(...s).then(o=>{this.ttl>0&&this.cache.set(this.ttl,e.func,...u,o),typeof o=="object"&&this.getInformationFromCache&&(o._mollitiaIsFromCache=!1),a(o)}).catch(()=>{var o;(o=this.logger)==null||o.debug(`${e.name}/${this.name} - Cache: Hit [Old]`),this.emit("cache-hit-old",e,u),a(m.res)}):((S=this.logger)==null||S.debug(`${e.name}/${this.name} - Cache: Hit`),this.emit("cache-hit",e,u),a(m.res))}else t(...s).then(f=>{this.ttl>0&&this.cache.set(this.ttl,e.func,...u,f),typeof f=="object"&&this.getInformationFromCache&&(f._mollitiaIsFromCache=!1),a(f)}).catch(f=>{l(f)})})}_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 K=2147483647;class G extends C{constructor(){super(...arguments);i(this,"concurrentSize");i(this,"queueSize");i(this,"maxQueueWait")}}class v extends Error{constructor(){super("Circuit is overloaded"),Object.setPrototypeOf(this,v.prototype)}}class x extends Error{constructor(){super("Waiting for too long in queue"),Object.setPrototypeOf(this,x.prototype)}}class Y extends P{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 Z extends g{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),l=this.getExecParams(e,s);return this.emit("execute",e,a,l),a}async _promiseBulkhead(e,t,...s){return new Promise((a,l)=>{const c=new Y(t,...s);if(this.concurrentBuffer.length<this.concurrentSize)c.execute().then(u=>{a(u)}).catch(u=>{l(u)}).finally(()=>{this.concurrentBuffer.splice(this.concurrentBuffer.indexOf(c),1),this.emit("update-concurrent-buffer",e,this.concurrentBuffer),this._addBufferedPromise(e)}),this.concurrentBuffer.push(c),this.emit("update-concurrent-buffer",e,this.concurrentBuffer);else if(this.queueBuffer.length<this.queueSize){this.queueBuffer.push(c),this.emit("update-queue-buffer",e,this.queueBuffer);let u;this.maxQueueWait<=K&&(u=setTimeout(()=>{this.queueBuffer.splice(this.queueBuffer.indexOf(c),1),this.emit("update-queue-buffer",e,this.queueBuffer),S.dispose(),f.dispose(),l(new x)},this.maxQueueWait));const m=c.on("execute",()=>{m.dispose(),clearTimeout(u)}),S=c.on("resolve",o=>{clearTimeout(u),this.concurrentBuffer.splice(this.concurrentBuffer.indexOf(c),1),this.emit("update-concurrent-buffer",e,this.concurrentBuffer),S.dispose(),f.dispose(),this._addBufferedPromise(e),a(o)}),f=c.on("reject",o=>{clearTimeout(u),this.concurrentBuffer.splice(this.concurrentBuffer.indexOf(c),1),this.emit("update-concurrent-buffer",e,this.concurrentBuffer),S.dispose(),f.dispose(),this._addBufferedPromise(e),l(o)})}else l(new v)})}_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 b extends Error{constructor(e,t){super("Ratelimited");i(this,"remainingTimeInRatelimit");this.name=t,this.remainingTimeInRatelimit=e,Object.setPrototypeOf(this,b.prototype)}}class ee extends g{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(m){(u=this.logger)==null||u.warn(m)}a!=null&&a.requests&&(this.requestsTime=a==null?void 0:a.requests);const l=this._promiseRatelimit(e,t,...s),c=this.getExecParams(e,s);return this.emit("execute",e,l,c),l}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 l;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 c=a-this.requestsTime[0];return c>this.limitPeriod?(this.requestsTime.splice(0,1),await this.addCurrentRequest(a),t(...s)):((l=this.logger)==null||l.debug(`${e.name}/${this.name} - Ratelimited`),this.emit("ratelimit",e),Promise.reject(new b(this.limitPeriod-c,this.name)))}}}class q extends Error{constructor(){super("Circuit is opened"),Object.setPrototypeOf(this,q.prototype)}}class I extends Error{constructor(){super("Max allowed requests reached"),Object.setPrototypeOf(this,I.prototype)}}var D=(h=>(h.CLOSED="closed",h.HALF_OPENED="half-opened",h.OPENED="opened",h))(D||{});class te extends C{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 y=(h=>(h[h.SUCCESS=0]="SUCCESS",h[h.FAILURE=1]="FAILURE",h[h.TIMEOUT=2]="TIMEOUT",h))(y||{});class M extends g{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(D,e.state)&&this.isValidTimestamp(e))}isValidRequest(e){return!!(e&&typeof e=="object"&&"result"in e&&this.isSomeEnum(y,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 c;try{const u=await this.getState();this.isValidData(u)&&(this.requests=u.requests?u.requests.map(m=>m.timestamp?{result:m.result,timestamp:m.timestamp}:{result:m.result}):[],u.state&&(this.state=u.state.state,this.stateTimestamp=u.state.timestamp))}catch(u){(c=this.logger)==null||c.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),l=this.getExecParams(e,s);return this.emit("execute",e,a,l),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 q);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:l}=await this.executePromise(e,...t);return this.requests.push({result:this.adjustRequestResult(s,l)}),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 I)}executePromise(e,...t){const s=new Date().getTime();return e(...t).then(a=>{const l=new Date().getTime();let c=0;return this.slowCallDurationThreshold!==0&&this.slowCallDurationThreshold!==1/0&&l-s>this.slowCallDurationThreshold&&(c=2),{requestResult:c,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 se extends M{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),l=this.adjustRequestResult(t,a);this.requests.push({result:l});const c=this.requests.length;let u=!1;return c>=this.minimumNumberOfCalls&&(c>this.slidingWindowSize&&(this.requests.splice(0,c-this.slidingWindowSize),u=!0,await this.setStateSecure([{key:"requests",value:this.requests}])),l!==y.SUCCESS&&(this.checkCallRatesClosed()||(await this.open(),u=!0))),u||await this.setStateSecure([{key:"requests",value:this.requests}]),t===y.FAILURE?Promise.reject(s):Promise.resolve(s)}}class ie extends M{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:l}=await this.executePromise(e,...t);this.filterCalls();const c=this.adjustRequestResult(s,l);this.requests.push({result:c,timestamp:new Date().getTime()});let u=!1;return this.requests.length>=this.minimumNumberOfCalls&&c!==y.SUCCESS&&(this.checkCallRatesClosed()||(await this.open(),u=!0)),u||await this.setStateSecure([{key:"requests",value:this.requests}],this.slidingWindowSize),s===y.FAILURE?Promise.reject(a):Promise.resolve(a)}}const ae="0.1.1";n.Addon=k,n.BreakerError=q,n.BreakerMaxAllowedRequestError=I,n.BreakerState=D,n.Bulkhead=Z,n.BulkheadOptions=G,n.BulkheadOverloadError=v,n.BulkheadQueueWaitError=x,n.Cache=X,n.CacheOptions=J,n.Circuit=H,n.CircuitFactory=F,n.CircuitOptions=B,n.Fallback=V,n.FallbackOptions=L,n.Module=g,n.ModuleOptions=C,n.NoFuncError=O,n.Ratelimit=ee,n.RatelimitError=b,n.Retry=$,n.RetryMode=_,n.RetryOptions=W,n.SlidingCountBreaker=se,n.SlidingTimeBreaker=ie,n.SlidingWindowBreaker=M,n.SlidingWindowBreakerOptions=te,n.SlidingWindowRequestResult=y,n.Timeout=A,n.TimeoutError=T,n.TimeoutOptions=N,n.circuits=R,n.modules=j,n.use=w,n.version=ae,Object.defineProperty(n,Symbol.toStringTag,{value:"Module"})});