import e from"@babel/runtime/helpers/classCallCheck";import t from"@babel/runtime/helpers/createClass";import i from"@babel/runtime/helpers/defineProperty";import{IDLE_CLEANUP_AFTER_MS as r,DEFAULT_CONFIG as o}from"./constants.js";function u(e,t){var i=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),i.push.apply(i,r)}return i}function n(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?u(Object(r),!0).forEach((function(t){i(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):u(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}var a=function(){function u(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};e(this,u),i(this,"buckets",new Map),i(this,"config",void 0),this.config=n(n(n({},o),t),{},{defaults:n(n({},o.defaults),t.defaults),overrides:n(n({},o.overrides),t.overrides)})}return t(u,[{key:"log",value:function(){if(this.config.debug){for(var e,t=arguments.length,i=new Array(t),r=0;r<t;r++)i[r]=arguments[r];(e=console).log.apply(e,["[RateLimiter]"].concat(i))}}},{key:"getOrCreateBucket",value:function(e,t,i){var r=this.buckets.get(e);if(!r){var o=n(n({},this.config.defaults),this.config.overrides[t]),u=o.maxTokens,a=o.refillRate,s=o.queueTimeout,l=o.maxQueueSize,c={appKey:t,appInstanceId:i,tokens:u,maxTokens:u,refillRate:a,queueTimeout:s,lastRefill:Date.now(),lastActivity:Date.now(),queue:[],refillTimer:null,maxQueueSize:l};return this.buckets.set(e,c),this.startRefillTimer(e,c),this.log("Bucket created",c),c}return r}},{key:"refill",value:function(e){var t=Date.now(),i=(t-e.lastRefill)/1e3*e.refillRate;i>0&&(e.tokens=Math.min(e.maxTokens,e.tokens+i),e.lastRefill=t)}},{key:"startRefillTimer",value:function(e,t){var i=this;t.refillTimer=setInterval((function(){i.refill(t),i.drainQueue(t),i.cleanupIdleIfNeeded(e,t)}),200)}},{key:"drainQueue",value:function(e){for(;e.queue.length>0&&e.tokens>=1;){e.tokens-=1,e.lastActivity=Date.now();var t=e.queue.shift();clearTimeout(null==t?void 0:t.timeoutId),null==t||t.resolve()}}},{key:"cleanupIdleIfNeeded",value:function(e,t){t.queue.length>0||Date.now()-t.lastActivity>=r&&(this.destroyBucket(t),this.buckets.delete(e))}},{key:"destroyBucket",value:function(e){e.refillTimer&&clearInterval(e.refillTimer),e.queue.forEach((function(e){clearTimeout(e.timeoutId),e.reject(new Error("[RateLimiter] Destroyed while request was queued"))})),e.queue=[]}},{key:"acquire",value:function(e,t){var i=this;if(!this.config.enabled)return Promise.resolve();var r="".concat(e,"|").concat(t),o=this.getOrCreateBucket(r,e,String(t));if(this.log("Request. Bucket:",r,"Tokens:",o.tokens),this.refill(o),o.tokens>=1)return o.tokens-=1,o.lastActivity=Date.now(),Promise.resolve();var u=o.queue.length+1,n={id:r,appKey:o.appKey,appInstanceId:o.appInstanceId,maxTokens:o.maxTokens,queueLength:u,queueTimeout:o.queueTimeout,refillRate:o.refillRate};return this.log("Bucket limit reached",n),function(e){var t=window[Symbol.for("corvaAPI.rateLimiterReport")];t?t({message:"[RateLimiter] Rate limit reached",bucket:e}):console.warn("[RateLimiter] Reporter not found")}(n),void 0!==o.maxQueueSize&&u>o.maxQueueSize?(this.log("Queue size limit exceeded",n),Promise.reject(new Error('[RateLimiter] Queue size limit exceeded for "'.concat(r,'". Limit: ').concat(o.maxQueueSize)))):new Promise((function(e,t){var u={};u.resolve=e,u.reject=t,u.timeoutId=setTimeout((function(){var e=o.queue.indexOf(u);-1!==e&&o.queue.splice(e,1),i.log("Queue timeout exceeded",n),t(new Error('[RateLimiter] Queue timeout exceeded for "'.concat(r,'" after ').concat(o.queueTimeout,"ms")))}),o.queueTimeout),o.queue.push(u)}))}},{key:"updateConfig",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};this.config=n(n(n({},this.config),e),{},{defaults:n(n({},this.config.defaults),e.defaults),overrides:n(n({},this.config.overrides),e.overrides)}),this.log("Config updated",e)}},{key:"destroy",value:function(){this.buckets.forEach(this.destroyBucket),this.buckets.clear()}}]),u}(),s=new a;export{a as RateLimiter,s as apiRequestsRateLimiter};
//# sourceMappingURL=rateLimiter.js.map
