"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/classCallCheck"),t=require("@babel/runtime/helpers/createClass"),i=require("@babel/runtime/helpers/defineProperty"),r=require("./constants.js");function u(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var o=u(e),n=u(t),a=u(i);function s(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 l(e){for(var t=1;t<arguments.length;t++){var i=null!=arguments[t]?arguments[t]:{};t%2?s(Object(i),!0).forEach((function(t){a.default(e,t,i[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(i)):s(Object(i)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(i,t))}))}return e}var c=function(){function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};o.default(this,e),a.default(this,"buckets",new Map),a.default(this,"config",void 0),this.config=l(l(l({},r.DEFAULT_CONFIG),t),{},{defaults:l(l({},r.DEFAULT_CONFIG.defaults),t.defaults),overrides:l(l({},r.DEFAULT_CONFIG.overrides),t.overrides)})}return n.default(e,[{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 u=l(l({},this.config.defaults),this.config.overrides[t]),o=u.maxTokens,n=u.refillRate,a=u.queueTimeout,s=u.maxQueueSize,c={appKey:t,appInstanceId:i,tokens:o,maxTokens:o,refillRate:n,queueTimeout:a,lastRefill:Date.now(),lastActivity:Date.now(),queue:[],refillTimer:null,maxQueueSize:s};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.IDLE_CLEANUP_AFTER_MS&&(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),u=this.getOrCreateBucket(r,e,String(t));if(this.log("Request. Bucket:",r,"Tokens:",u.tokens),this.refill(u),u.tokens>=1)return u.tokens-=1,u.lastActivity=Date.now(),Promise.resolve();var o=u.queue.length+1,n={id:r,appKey:u.appKey,appInstanceId:u.appInstanceId,maxTokens:u.maxTokens,queueLength:o,queueTimeout:u.queueTimeout,refillRate:u.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!==u.maxQueueSize&&o>u.maxQueueSize?(this.log("Queue size limit exceeded",n),Promise.reject(new Error('[RateLimiter] Queue size limit exceeded for "'.concat(r,'". Limit: ').concat(u.maxQueueSize)))):new Promise((function(e,t){var o={};o.resolve=e,o.reject=t,o.timeoutId=setTimeout((function(){var e=u.queue.indexOf(o);-1!==e&&u.queue.splice(e,1),i.log("Queue timeout exceeded",n),t(new Error('[RateLimiter] Queue timeout exceeded for "'.concat(r,'" after ').concat(u.queueTimeout,"ms")))}),u.queueTimeout),u.queue.push(o)}))}},{key:"updateConfig",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};this.config=l(l(l({},this.config),e),{},{defaults:l(l({},this.config.defaults),e.defaults),overrides:l(l({},this.config.overrides),e.overrides)}),this.log("Config updated",e)}},{key:"destroy",value:function(){this.buckets.forEach(this.destroyBucket),this.buckets.clear()}}]),e}(),f=new c;exports.RateLimiter=c,exports.apiRequestsRateLimiter=f;
//# sourceMappingURL=rateLimiter.js.map
