UNPKG

43.1 kBJavaScriptView Raw
1/**
2 * This file contains the Bottleneck library (MIT), compiled to ES2017, and without Clustering support.
3 * https://github.com/SGrondin/bottleneck
4 */
5(function (global, factory) {
6 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
7 typeof define === 'function' && define.amd ? define(factory) :
8 (global.Bottleneck = factory());
9}(this, (function () { 'use strict';
10
11 var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
12
13 function getCjsExportFromNamespace (n) {
14 return n && n['default'] || n;
15 }
16
17 var load = function(received, defaults, onto = {}) {
18 var k, ref, v;
19 for (k in defaults) {
20 v = defaults[k];
21 onto[k] = (ref = received[k]) != null ? ref : v;
22 }
23 return onto;
24 };
25
26 var overwrite = function(received, defaults, onto = {}) {
27 var k, v;
28 for (k in received) {
29 v = received[k];
30 if (defaults[k] !== void 0) {
31 onto[k] = v;
32 }
33 }
34 return onto;
35 };
36
37 var parser = {
38 load: load,
39 overwrite: overwrite
40 };
41
42 var DLList;
43
44 DLList = class DLList {
45 constructor(incr, decr) {
46 this.incr = incr;
47 this.decr = decr;
48 this._first = null;
49 this._last = null;
50 this.length = 0;
51 }
52
53 push(value) {
54 var node;
55 this.length++;
56 if (typeof this.incr === "function") {
57 this.incr();
58 }
59 node = {
60 value,
61 prev: this._last,
62 next: null
63 };
64 if (this._last != null) {
65 this._last.next = node;
66 this._last = node;
67 } else {
68 this._first = this._last = node;
69 }
70 return void 0;
71 }
72
73 shift() {
74 var value;
75 if (this._first == null) {
76 return;
77 } else {
78 this.length--;
79 if (typeof this.decr === "function") {
80 this.decr();
81 }
82 }
83 value = this._first.value;
84 if ((this._first = this._first.next) != null) {
85 this._first.prev = null;
86 } else {
87 this._last = null;
88 }
89 return value;
90 }
91
92 first() {
93 if (this._first != null) {
94 return this._first.value;
95 }
96 }
97
98 getArray() {
99 var node, ref, results;
100 node = this._first;
101 results = [];
102 while (node != null) {
103 results.push((ref = node, node = node.next, ref.value));
104 }
105 return results;
106 }
107
108 forEachShift(cb) {
109 var node;
110 node = this.shift();
111 while (node != null) {
112 (cb(node), node = this.shift());
113 }
114 return void 0;
115 }
116
117 debug() {
118 var node, ref, ref1, ref2, results;
119 node = this._first;
120 results = [];
121 while (node != null) {
122 results.push((ref = node, node = node.next, {
123 value: ref.value,
124 prev: (ref1 = ref.prev) != null ? ref1.value : void 0,
125 next: (ref2 = ref.next) != null ? ref2.value : void 0
126 }));
127 }
128 return results;
129 }
130
131 };
132
133 var DLList_1 = DLList;
134
135 var Events;
136
137 Events = class Events {
138 constructor(instance) {
139 this.instance = instance;
140 this._events = {};
141 if ((this.instance.on != null) || (this.instance.once != null) || (this.instance.removeAllListeners != null)) {
142 throw new Error("An Emitter already exists for this object");
143 }
144 this.instance.on = (name, cb) => {
145 return this._addListener(name, "many", cb);
146 };
147 this.instance.once = (name, cb) => {
148 return this._addListener(name, "once", cb);
149 };
150 this.instance.removeAllListeners = (name = null) => {
151 if (name != null) {
152 return delete this._events[name];
153 } else {
154 return this._events = {};
155 }
156 };
157 }
158
159 _addListener(name, status, cb) {
160 var base;
161 if ((base = this._events)[name] == null) {
162 base[name] = [];
163 }
164 this._events[name].push({cb, status});
165 return this.instance;
166 }
167
168 listenerCount(name) {
169 if (this._events[name] != null) {
170 return this._events[name].length;
171 } else {
172 return 0;
173 }
174 }
175
176 async trigger(name, ...args) {
177 var e, promises;
178 try {
179 if (name !== "debug") {
180 this.trigger("debug", `Event triggered: ${name}`, args);
181 }
182 if (this._events[name] == null) {
183 return;
184 }
185 this._events[name] = this._events[name].filter(function(listener) {
186 return listener.status !== "none";
187 });
188 promises = this._events[name].map(async(listener) => {
189 var e, returned;
190 if (listener.status === "none") {
191 return;
192 }
193 if (listener.status === "once") {
194 listener.status = "none";
195 }
196 try {
197 returned = typeof listener.cb === "function" ? listener.cb(...args) : void 0;
198 if (typeof (returned != null ? returned.then : void 0) === "function") {
199 return (await returned);
200 } else {
201 return returned;
202 }
203 } catch (error) {
204 e = error;
205 {
206 this.trigger("error", e);
207 }
208 return null;
209 }
210 });
211 return ((await Promise.all(promises))).find(function(x) {
212 return x != null;
213 });
214 } catch (error) {
215 e = error;
216 {
217 this.trigger("error", e);
218 }
219 return null;
220 }
221 }
222
223 };
224
225 var Events_1 = Events;
226
227 var DLList$1, Events$1, Queues;
228
229 DLList$1 = DLList_1;
230
231 Events$1 = Events_1;
232
233 Queues = class Queues {
234 constructor(num_priorities) {
235 var i;
236 this.Events = new Events$1(this);
237 this._length = 0;
238 this._lists = (function() {
239 var j, ref, results;
240 results = [];
241 for (i = j = 1, ref = num_priorities; (1 <= ref ? j <= ref : j >= ref); i = 1 <= ref ? ++j : --j) {
242 results.push(new DLList$1((() => {
243 return this.incr();
244 }), (() => {
245 return this.decr();
246 })));
247 }
248 return results;
249 }).call(this);
250 }
251
252 incr() {
253 if (this._length++ === 0) {
254 return this.Events.trigger("leftzero");
255 }
256 }
257
258 decr() {
259 if (--this._length === 0) {
260 return this.Events.trigger("zero");
261 }
262 }
263
264 push(job) {
265 return this._lists[job.options.priority].push(job);
266 }
267
268 queued(priority) {
269 if (priority != null) {
270 return this._lists[priority].length;
271 } else {
272 return this._length;
273 }
274 }
275
276 shiftAll(fn) {
277 return this._lists.forEach(function(list) {
278 return list.forEachShift(fn);
279 });
280 }
281
282 getFirst(arr = this._lists) {
283 var j, len, list;
284 for (j = 0, len = arr.length; j < len; j++) {
285 list = arr[j];
286 if (list.length > 0) {
287 return list;
288 }
289 }
290 return [];
291 }
292
293 shiftLastFrom(priority) {
294 return this.getFirst(this._lists.slice(priority).reverse()).shift();
295 }
296
297 };
298
299 var Queues_1 = Queues;
300
301 var BottleneckError;
302
303 BottleneckError = class BottleneckError extends Error {};
304
305 var BottleneckError_1 = BottleneckError;
306
307 var BottleneckError$1, DEFAULT_PRIORITY, Job, NUM_PRIORITIES, parser$1;
308
309 NUM_PRIORITIES = 10;
310
311 DEFAULT_PRIORITY = 5;
312
313 parser$1 = parser;
314
315 BottleneckError$1 = BottleneckError_1;
316
317 Job = class Job {
318 constructor(task, args, options, jobDefaults, rejectOnDrop, Events, _states, Promise) {
319 this.task = task;
320 this.args = args;
321 this.rejectOnDrop = rejectOnDrop;
322 this.Events = Events;
323 this._states = _states;
324 this.Promise = Promise;
325 this.options = parser$1.load(options, jobDefaults);
326 this.options.priority = this._sanitizePriority(this.options.priority);
327 if (this.options.id === jobDefaults.id) {
328 this.options.id = `${this.options.id}-${this._randomIndex()}`;
329 }
330 this.promise = new this.Promise((_resolve, _reject) => {
331 this._resolve = _resolve;
332 this._reject = _reject;
333 });
334 this.retryCount = 0;
335 }
336
337 _sanitizePriority(priority) {
338 var sProperty;
339 sProperty = ~~priority !== priority ? DEFAULT_PRIORITY : priority;
340 if (sProperty < 0) {
341 return 0;
342 } else if (sProperty > NUM_PRIORITIES - 1) {
343 return NUM_PRIORITIES - 1;
344 } else {
345 return sProperty;
346 }
347 }
348
349 _randomIndex() {
350 return Math.random().toString(36).slice(2);
351 }
352
353 doDrop({error, message = "This job has been dropped by Bottleneck"} = {}) {
354 if (this._states.remove(this.options.id)) {
355 if (this.rejectOnDrop) {
356 this._reject(error != null ? error : new BottleneckError$1(message));
357 }
358 this.Events.trigger("dropped", {args: this.args, options: this.options, task: this.task, promise: this.promise});
359 return true;
360 } else {
361 return false;
362 }
363 }
364
365 _assertStatus(expected) {
366 var status;
367 status = this._states.jobStatus(this.options.id);
368 if (!(status === expected || (expected === "DONE" && status === null))) {
369 throw new BottleneckError$1(`Invalid job status ${status}, expected ${expected}. Please open an issue at https://github.com/SGrondin/bottleneck/issues`);
370 }
371 }
372
373 doReceive() {
374 this._states.start(this.options.id);
375 return this.Events.trigger("received", {args: this.args, options: this.options});
376 }
377
378 doQueue(reachedHWM, blocked) {
379 this._assertStatus("RECEIVED");
380 this._states.next(this.options.id);
381 return this.Events.trigger("queued", {args: this.args, options: this.options, reachedHWM, blocked});
382 }
383
384 doRun() {
385 if (this.retryCount === 0) {
386 this._assertStatus("QUEUED");
387 this._states.next(this.options.id);
388 } else {
389 this._assertStatus("EXECUTING");
390 }
391 return this.Events.trigger("scheduled", {args: this.args, options: this.options});
392 }
393
394 async doExecute(chained, clearGlobalState, run, free) {
395 var error, eventInfo, passed;
396 if (this.retryCount === 0) {
397 this._assertStatus("RUNNING");
398 this._states.next(this.options.id);
399 } else {
400 this._assertStatus("EXECUTING");
401 }
402 eventInfo = {args: this.args, options: this.options, retryCount: this.retryCount};
403 this.Events.trigger("executing", eventInfo);
404 try {
405 passed = (await (chained != null ? chained.schedule(this.options, this.task, ...this.args) : this.task(...this.args)));
406 if (clearGlobalState()) {
407 this.doDone(eventInfo);
408 await free(this.options, eventInfo);
409 this._assertStatus("DONE");
410 return this._resolve(passed);
411 }
412 } catch (error1) {
413 error = error1;
414 return this._onFailure(error, eventInfo, clearGlobalState, run, free);
415 }
416 }
417
418 doExpire(clearGlobalState, run, free) {
419 var error, eventInfo;
420 this._assertStatus("EXECUTING");
421 eventInfo = {args: this.args, options: this.options, retryCount: this.retryCount};
422 error = new BottleneckError$1(`This job timed out after ${this.options.expiration} ms.`);
423 return this._onFailure(error, eventInfo, clearGlobalState, run, free);
424 }
425
426 async _onFailure(error, eventInfo, clearGlobalState, run, free) {
427 var retry, retryAfter;
428 if (clearGlobalState()) {
429 retry = (await this.Events.trigger("failed", error, eventInfo));
430 if (retry != null) {
431 retryAfter = ~~retry;
432 this.Events.trigger("retry", `Retrying ${this.options.id} after ${retryAfter} ms`, eventInfo);
433 this.retryCount++;
434 return run(retryAfter);
435 } else {
436 this.doDone(eventInfo);
437 await free(this.options, eventInfo);
438 this._assertStatus("DONE");
439 return this._reject(error);
440 }
441 }
442 }
443
444 doDone(eventInfo) {
445 this._assertStatus("EXECUTING");
446 this._states.next(this.options.id);
447 return this.Events.trigger("done", eventInfo);
448 }
449
450 };
451
452 var Job_1 = Job;
453
454 var BottleneckError$2, LocalDatastore, parser$2;
455
456 parser$2 = parser;
457
458 BottleneckError$2 = BottleneckError_1;
459
460 LocalDatastore = class LocalDatastore {
461 constructor(instance, storeOptions, storeInstanceOptions) {
462 this.instance = instance;
463 this.storeOptions = storeOptions;
464 this.clientId = this.instance._randomIndex();
465 parser$2.load(storeInstanceOptions, storeInstanceOptions, this);
466 this._nextRequest = this._lastReservoirRefresh = this._lastReservoirIncrease = Date.now();
467 this._running = 0;
468 this._done = 0;
469 this._unblockTime = 0;
470 this.ready = this.Promise.resolve();
471 this.clients = {};
472 this._startHeartbeat();
473 }
474
475 _startHeartbeat() {
476 var base;
477 if ((this.heartbeat == null) && (((this.storeOptions.reservoirRefreshInterval != null) && (this.storeOptions.reservoirRefreshAmount != null)) || ((this.storeOptions.reservoirIncreaseInterval != null) && (this.storeOptions.reservoirIncreaseAmount != null)))) {
478 return typeof (base = (this.heartbeat = setInterval(() => {
479 var amount, incr, maximum, now, reservoir;
480 now = Date.now();
481 if ((this.storeOptions.reservoirRefreshInterval != null) && now >= this._lastReservoirRefresh + this.storeOptions.reservoirRefreshInterval) {
482 this._lastReservoirRefresh = now;
483 this.storeOptions.reservoir = this.storeOptions.reservoirRefreshAmount;
484 this.instance._drainAll(this.computeCapacity());
485 }
486 if ((this.storeOptions.reservoirIncreaseInterval != null) && now >= this._lastReservoirIncrease + this.storeOptions.reservoirIncreaseInterval) {
487 ({
488 reservoirIncreaseAmount: amount,
489 reservoirIncreaseMaximum: maximum,
490 reservoir
491 } = this.storeOptions);
492 this._lastReservoirIncrease = now;
493 incr = maximum != null ? Math.min(amount, maximum - reservoir) : amount;
494 if (incr > 0) {
495 this.storeOptions.reservoir += incr;
496 return this.instance._drainAll(this.computeCapacity());
497 }
498 }
499 }, this.heartbeatInterval))).unref === "function" ? base.unref() : void 0;
500 } else {
501 return clearInterval(this.heartbeat);
502 }
503 }
504
505 async __publish__(message) {
506 await this.yieldLoop();
507 return this.instance.Events.trigger("message", message.toString());
508 }
509
510 async __disconnect__(flush) {
511 await this.yieldLoop();
512 clearInterval(this.heartbeat);
513 return this.Promise.resolve();
514 }
515
516 yieldLoop(t = 0) {
517 return new this.Promise(function(resolve, reject) {
518 return setTimeout(resolve, t);
519 });
520 }
521
522 computePenalty() {
523 var ref;
524 return (ref = this.storeOptions.penalty) != null ? ref : (15 * this.storeOptions.minTime) || 5000;
525 }
526
527 async __updateSettings__(options) {
528 await this.yieldLoop();
529 parser$2.overwrite(options, options, this.storeOptions);
530 this._startHeartbeat();
531 this.instance._drainAll(this.computeCapacity());
532 return true;
533 }
534
535 async __running__() {
536 await this.yieldLoop();
537 return this._running;
538 }
539
540 async __queued__() {
541 await this.yieldLoop();
542 return this.instance.queued();
543 }
544
545 async __done__() {
546 await this.yieldLoop();
547 return this._done;
548 }
549
550 async __groupCheck__(time) {
551 await this.yieldLoop();
552 return (this._nextRequest + this.timeout) < time;
553 }
554
555 computeCapacity() {
556 var maxConcurrent, reservoir;
557 ({maxConcurrent, reservoir} = this.storeOptions);
558 if ((maxConcurrent != null) && (reservoir != null)) {
559 return Math.min(maxConcurrent - this._running, reservoir);
560 } else if (maxConcurrent != null) {
561 return maxConcurrent - this._running;
562 } else if (reservoir != null) {
563 return reservoir;
564 } else {
565 return null;
566 }
567 }
568
569 conditionsCheck(weight) {
570 var capacity;
571 capacity = this.computeCapacity();
572 return (capacity == null) || weight <= capacity;
573 }
574
575 async __incrementReservoir__(incr) {
576 var reservoir;
577 await this.yieldLoop();
578 reservoir = this.storeOptions.reservoir += incr;
579 this.instance._drainAll(this.computeCapacity());
580 return reservoir;
581 }
582
583 async __currentReservoir__() {
584 await this.yieldLoop();
585 return this.storeOptions.reservoir;
586 }
587
588 isBlocked(now) {
589 return this._unblockTime >= now;
590 }
591
592 check(weight, now) {
593 return this.conditionsCheck(weight) && (this._nextRequest - now) <= 0;
594 }
595
596 async __check__(weight) {
597 var now;
598 await this.yieldLoop();
599 now = Date.now();
600 return this.check(weight, now);
601 }
602
603 async __register__(index, weight, expiration) {
604 var now, wait;
605 await this.yieldLoop();
606 now = Date.now();
607 if (this.conditionsCheck(weight)) {
608 this._running += weight;
609 if (this.storeOptions.reservoir != null) {
610 this.storeOptions.reservoir -= weight;
611 }
612 wait = Math.max(this._nextRequest - now, 0);
613 this._nextRequest = now + wait + this.storeOptions.minTime;
614 return {
615 success: true,
616 wait,
617 reservoir: this.storeOptions.reservoir
618 };
619 } else {
620 return {
621 success: false
622 };
623 }
624 }
625
626 strategyIsBlock() {
627 return this.storeOptions.strategy === 3;
628 }
629
630 async __submit__(queueLength, weight) {
631 var blocked, now, reachedHWM;
632 await this.yieldLoop();
633 if ((this.storeOptions.maxConcurrent != null) && weight > this.storeOptions.maxConcurrent) {
634 throw new BottleneckError$2(`Impossible to add a job having a weight of ${weight} to a limiter having a maxConcurrent setting of ${this.storeOptions.maxConcurrent}`);
635 }
636 now = Date.now();
637 reachedHWM = (this.storeOptions.highWater != null) && queueLength === this.storeOptions.highWater && !this.check(weight, now);
638 blocked = this.strategyIsBlock() && (reachedHWM || this.isBlocked(now));
639 if (blocked) {
640 this._unblockTime = now + this.computePenalty();
641 this._nextRequest = this._unblockTime + this.storeOptions.minTime;
642 this.instance._dropAllQueued();
643 }
644 return {
645 reachedHWM,
646 blocked,
647 strategy: this.storeOptions.strategy
648 };
649 }
650
651 async __free__(index, weight) {
652 await this.yieldLoop();
653 this._running -= weight;
654 this._done += weight;
655 this.instance._drainAll(this.computeCapacity());
656 return {
657 running: this._running
658 };
659 }
660
661 };
662
663 var LocalDatastore_1 = LocalDatastore;
664
665 var BottleneckError$3, States;
666
667 BottleneckError$3 = BottleneckError_1;
668
669 States = class States {
670 constructor(status1) {
671 this.status = status1;
672 this._jobs = {};
673 this.counts = this.status.map(function() {
674 return 0;
675 });
676 }
677
678 next(id) {
679 var current, next;
680 current = this._jobs[id];
681 next = current + 1;
682 if ((current != null) && next < this.status.length) {
683 this.counts[current]--;
684 this.counts[next]++;
685 return this._jobs[id]++;
686 } else if (current != null) {
687 this.counts[current]--;
688 return delete this._jobs[id];
689 }
690 }
691
692 start(id) {
693 var initial;
694 initial = 0;
695 this._jobs[id] = initial;
696 return this.counts[initial]++;
697 }
698
699 remove(id) {
700 var current;
701 current = this._jobs[id];
702 if (current != null) {
703 this.counts[current]--;
704 delete this._jobs[id];
705 }
706 return current != null;
707 }
708
709 jobStatus(id) {
710 var ref;
711 return (ref = this.status[this._jobs[id]]) != null ? ref : null;
712 }
713
714 statusJobs(status) {
715 var k, pos, ref, results, v;
716 if (status != null) {
717 pos = this.status.indexOf(status);
718 if (pos < 0) {
719 throw new BottleneckError$3(`status must be one of ${this.status.join(', ')}`);
720 }
721 ref = this._jobs;
722 results = [];
723 for (k in ref) {
724 v = ref[k];
725 if (v === pos) {
726 results.push(k);
727 }
728 }
729 return results;
730 } else {
731 return Object.keys(this._jobs);
732 }
733 }
734
735 statusCounts() {
736 return this.counts.reduce(((acc, v, i) => {
737 acc[this.status[i]] = v;
738 return acc;
739 }), {});
740 }
741
742 };
743
744 var States_1 = States;
745
746 var DLList$2, Sync;
747
748 DLList$2 = DLList_1;
749
750 Sync = class Sync {
751 constructor(name, Promise) {
752 this.schedule = this.schedule.bind(this);
753 this.name = name;
754 this.Promise = Promise;
755 this._running = 0;
756 this._queue = new DLList$2();
757 }
758
759 isEmpty() {
760 return this._queue.length === 0;
761 }
762
763 async _tryToRun() {
764 var args, cb, error, reject, resolve, returned, task;
765 if ((this._running < 1) && this._queue.length > 0) {
766 this._running++;
767 ({task, args, resolve, reject} = this._queue.shift());
768 cb = (await (async function() {
769 try {
770 returned = (await task(...args));
771 return function() {
772 return resolve(returned);
773 };
774 } catch (error1) {
775 error = error1;
776 return function() {
777 return reject(error);
778 };
779 }
780 })());
781 this._running--;
782 this._tryToRun();
783 return cb();
784 }
785 }
786
787 schedule(task, ...args) {
788 var promise, reject, resolve;
789 resolve = reject = null;
790 promise = new this.Promise(function(_resolve, _reject) {
791 resolve = _resolve;
792 return reject = _reject;
793 });
794 this._queue.push({task, args, resolve, reject});
795 this._tryToRun();
796 return promise;
797 }
798
799 };
800
801 var Sync_1 = Sync;
802
803 var version = "2.19.3";
804 var version$1 = {
805 version: version
806 };
807
808 var version$2 = /*#__PURE__*/Object.freeze({
809 version: version,
810 default: version$1
811 });
812
813 var require$$2 = () => console.log('You must import the full version of Bottleneck in order to use this feature.');
814
815 var require$$3 = () => console.log('You must import the full version of Bottleneck in order to use this feature.');
816
817 var require$$4 = () => console.log('You must import the full version of Bottleneck in order to use this feature.');
818
819 var Events$2, Group, IORedisConnection$1, RedisConnection$1, Scripts$1, parser$3;
820
821 parser$3 = parser;
822
823 Events$2 = Events_1;
824
825 RedisConnection$1 = require$$2;
826
827 IORedisConnection$1 = require$$3;
828
829 Scripts$1 = require$$4;
830
831 Group = (function() {
832 class Group {
833 constructor(limiterOptions = {}) {
834 this.deleteKey = this.deleteKey.bind(this);
835 this.limiterOptions = limiterOptions;
836 parser$3.load(this.limiterOptions, this.defaults, this);
837 this.Events = new Events$2(this);
838 this.instances = {};
839 this.Bottleneck = Bottleneck_1;
840 this._startAutoCleanup();
841 this.sharedConnection = this.connection != null;
842 if (this.connection == null) {
843 if (this.limiterOptions.datastore === "redis") {
844 this.connection = new RedisConnection$1(Object.assign({}, this.limiterOptions, {Events: this.Events}));
845 } else if (this.limiterOptions.datastore === "ioredis") {
846 this.connection = new IORedisConnection$1(Object.assign({}, this.limiterOptions, {Events: this.Events}));
847 }
848 }
849 }
850
851 key(key = "") {
852 var ref;
853 return (ref = this.instances[key]) != null ? ref : (() => {
854 var limiter;
855 limiter = this.instances[key] = new this.Bottleneck(Object.assign(this.limiterOptions, {
856 id: `${this.id}-${key}`,
857 timeout: this.timeout,
858 connection: this.connection
859 }));
860 this.Events.trigger("created", limiter, key);
861 return limiter;
862 })();
863 }
864
865 async deleteKey(key = "") {
866 var deleted, instance;
867 instance = this.instances[key];
868 if (this.connection) {
869 deleted = (await this.connection.__runCommand__(['del', ...Scripts$1.allKeys(`${this.id}-${key}`)]));
870 }
871 if (instance != null) {
872 delete this.instances[key];
873 await instance.disconnect();
874 }
875 return (instance != null) || deleted > 0;
876 }
877
878 limiters() {
879 var k, ref, results, v;
880 ref = this.instances;
881 results = [];
882 for (k in ref) {
883 v = ref[k];
884 results.push({
885 key: k,
886 limiter: v
887 });
888 }
889 return results;
890 }
891
892 keys() {
893 return Object.keys(this.instances);
894 }
895
896 async clusterKeys() {
897 var cursor, end, found, i, k, keys, len, next, start;
898 if (this.connection == null) {
899 return this.Promise.resolve(this.keys());
900 }
901 keys = [];
902 cursor = null;
903 start = `b_${this.id}-`.length;
904 end = "_settings".length;
905 while (cursor !== 0) {
906 [next, found] = (await this.connection.__runCommand__(["scan", cursor != null ? cursor : 0, "match", `b_${this.id}-*_settings`, "count", 10000]));
907 cursor = ~~next;
908 for (i = 0, len = found.length; i < len; i++) {
909 k = found[i];
910 keys.push(k.slice(start, -end));
911 }
912 }
913 return keys;
914 }
915
916 _startAutoCleanup() {
917 var base;
918 clearInterval(this.interval);
919 return typeof (base = (this.interval = setInterval(async() => {
920 var e, k, ref, results, time, v;
921 time = Date.now();
922 ref = this.instances;
923 results = [];
924 for (k in ref) {
925 v = ref[k];
926 try {
927 if ((await v._store.__groupCheck__(time))) {
928 results.push(this.deleteKey(k));
929 } else {
930 results.push(void 0);
931 }
932 } catch (error) {
933 e = error;
934 results.push(v.Events.trigger("error", e));
935 }
936 }
937 return results;
938 }, this.timeout / 2))).unref === "function" ? base.unref() : void 0;
939 }
940
941 updateSettings(options = {}) {
942 parser$3.overwrite(options, this.defaults, this);
943 parser$3.overwrite(options, options, this.limiterOptions);
944 if (options.timeout != null) {
945 return this._startAutoCleanup();
946 }
947 }
948
949 disconnect(flush = true) {
950 var ref;
951 if (!this.sharedConnection) {
952 return (ref = this.connection) != null ? ref.disconnect(flush) : void 0;
953 }
954 }
955
956 }
957 Group.prototype.defaults = {
958 timeout: 1000 * 60 * 5,
959 connection: null,
960 Promise: Promise,
961 id: "group-key"
962 };
963
964 return Group;
965
966 }).call(commonjsGlobal);
967
968 var Group_1 = Group;
969
970 var Batcher, Events$3, parser$4;
971
972 parser$4 = parser;
973
974 Events$3 = Events_1;
975
976 Batcher = (function() {
977 class Batcher {
978 constructor(options = {}) {
979 this.options = options;
980 parser$4.load(this.options, this.defaults, this);
981 this.Events = new Events$3(this);
982 this._arr = [];
983 this._resetPromise();
984 this._lastFlush = Date.now();
985 }
986
987 _resetPromise() {
988 return this._promise = new this.Promise((res, rej) => {
989 return this._resolve = res;
990 });
991 }
992
993 _flush() {
994 clearTimeout(this._timeout);
995 this._lastFlush = Date.now();
996 this._resolve();
997 this.Events.trigger("batch", this._arr);
998 this._arr = [];
999 return this._resetPromise();
1000 }
1001
1002 add(data) {
1003 var ret;
1004 this._arr.push(data);
1005 ret = this._promise;
1006 if (this._arr.length === this.maxSize) {
1007 this._flush();
1008 } else if ((this.maxTime != null) && this._arr.length === 1) {
1009 this._timeout = setTimeout(() => {
1010 return this._flush();
1011 }, this.maxTime);
1012 }
1013 return ret;
1014 }
1015
1016 }
1017 Batcher.prototype.defaults = {
1018 maxTime: null,
1019 maxSize: null,
1020 Promise: Promise
1021 };
1022
1023 return Batcher;
1024
1025 }).call(commonjsGlobal);
1026
1027 var Batcher_1 = Batcher;
1028
1029 var require$$4$1 = () => console.log('You must import the full version of Bottleneck in order to use this feature.');
1030
1031 var require$$8 = getCjsExportFromNamespace(version$2);
1032
1033 var Bottleneck, DEFAULT_PRIORITY$1, Events$4, Job$1, LocalDatastore$1, NUM_PRIORITIES$1, Queues$1, RedisDatastore$1, States$1, Sync$1, parser$5,
1034 splice = [].splice;
1035
1036 NUM_PRIORITIES$1 = 10;
1037
1038 DEFAULT_PRIORITY$1 = 5;
1039
1040 parser$5 = parser;
1041
1042 Queues$1 = Queues_1;
1043
1044 Job$1 = Job_1;
1045
1046 LocalDatastore$1 = LocalDatastore_1;
1047
1048 RedisDatastore$1 = require$$4$1;
1049
1050 Events$4 = Events_1;
1051
1052 States$1 = States_1;
1053
1054 Sync$1 = Sync_1;
1055
1056 Bottleneck = (function() {
1057 class Bottleneck {
1058 constructor(options = {}, ...invalid) {
1059 var storeInstanceOptions, storeOptions;
1060 this._addToQueue = this._addToQueue.bind(this);
1061 this._validateOptions(options, invalid);
1062 parser$5.load(options, this.instanceDefaults, this);
1063 this._queues = new Queues$1(NUM_PRIORITIES$1);
1064 this._scheduled = {};
1065 this._states = new States$1(["RECEIVED", "QUEUED", "RUNNING", "EXECUTING"].concat(this.trackDoneStatus ? ["DONE"] : []));
1066 this._limiter = null;
1067 this.Events = new Events$4(this);
1068 this._submitLock = new Sync$1("submit", this.Promise);
1069 this._registerLock = new Sync$1("register", this.Promise);
1070 storeOptions = parser$5.load(options, this.storeDefaults, {});
1071 this._store = (function() {
1072 if (this.datastore === "redis" || this.datastore === "ioredis" || (this.connection != null)) {
1073 storeInstanceOptions = parser$5.load(options, this.redisStoreDefaults, {});
1074 return new RedisDatastore$1(this, storeOptions, storeInstanceOptions);
1075 } else if (this.datastore === "local") {
1076 storeInstanceOptions = parser$5.load(options, this.localStoreDefaults, {});
1077 return new LocalDatastore$1(this, storeOptions, storeInstanceOptions);
1078 } else {
1079 throw new Bottleneck.prototype.BottleneckError(`Invalid datastore type: ${this.datastore}`);
1080 }
1081 }).call(this);
1082 this._queues.on("leftzero", () => {
1083 var ref;
1084 return (ref = this._store.heartbeat) != null ? typeof ref.ref === "function" ? ref.ref() : void 0 : void 0;
1085 });
1086 this._queues.on("zero", () => {
1087 var ref;
1088 return (ref = this._store.heartbeat) != null ? typeof ref.unref === "function" ? ref.unref() : void 0 : void 0;
1089 });
1090 }
1091
1092 _validateOptions(options, invalid) {
1093 if (!((options != null) && typeof options === "object" && invalid.length === 0)) {
1094 throw new Bottleneck.prototype.BottleneckError("Bottleneck v2 takes a single object argument. Refer to https://github.com/SGrondin/bottleneck#upgrading-to-v2 if you're upgrading from Bottleneck v1.");
1095 }
1096 }
1097
1098 ready() {
1099 return this._store.ready;
1100 }
1101
1102 clients() {
1103 return this._store.clients;
1104 }
1105
1106 channel() {
1107 return `b_${this.id}`;
1108 }
1109
1110 channel_client() {
1111 return `b_${this.id}_${this._store.clientId}`;
1112 }
1113
1114 publish(message) {
1115 return this._store.__publish__(message);
1116 }
1117
1118 disconnect(flush = true) {
1119 return this._store.__disconnect__(flush);
1120 }
1121
1122 chain(_limiter) {
1123 this._limiter = _limiter;
1124 return this;
1125 }
1126
1127 queued(priority) {
1128 return this._queues.queued(priority);
1129 }
1130
1131 clusterQueued() {
1132 return this._store.__queued__();
1133 }
1134
1135 empty() {
1136 return this.queued() === 0 && this._submitLock.isEmpty();
1137 }
1138
1139 running() {
1140 return this._store.__running__();
1141 }
1142
1143 done() {
1144 return this._store.__done__();
1145 }
1146
1147 jobStatus(id) {
1148 return this._states.jobStatus(id);
1149 }
1150
1151 jobs(status) {
1152 return this._states.statusJobs(status);
1153 }
1154
1155 counts() {
1156 return this._states.statusCounts();
1157 }
1158
1159 _randomIndex() {
1160 return Math.random().toString(36).slice(2);
1161 }
1162
1163 check(weight = 1) {
1164 return this._store.__check__(weight);
1165 }
1166
1167 _clearGlobalState(index) {
1168 if (this._scheduled[index] != null) {
1169 clearTimeout(this._scheduled[index].expiration);
1170 delete this._scheduled[index];
1171 return true;
1172 } else {
1173 return false;
1174 }
1175 }
1176
1177 async _free(index, job, options, eventInfo) {
1178 var e, running;
1179 try {
1180 ({running} = (await this._store.__free__(index, options.weight)));
1181 this.Events.trigger("debug", `Freed ${options.id}`, eventInfo);
1182 if (running === 0 && this.empty()) {
1183 return this.Events.trigger("idle");
1184 }
1185 } catch (error1) {
1186 e = error1;
1187 return this.Events.trigger("error", e);
1188 }
1189 }
1190
1191 _run(index, job, wait) {
1192 var clearGlobalState, free, run;
1193 job.doRun();
1194 clearGlobalState = this._clearGlobalState.bind(this, index);
1195 run = this._run.bind(this, index, job);
1196 free = this._free.bind(this, index, job);
1197 return this._scheduled[index] = {
1198 timeout: setTimeout(() => {
1199 return job.doExecute(this._limiter, clearGlobalState, run, free);
1200 }, wait),
1201 expiration: job.options.expiration != null ? setTimeout(function() {
1202 return job.doExpire(clearGlobalState, run, free);
1203 }, wait + job.options.expiration) : void 0,
1204 job: job
1205 };
1206 }
1207
1208 _drainOne(capacity) {
1209 return this._registerLock.schedule(() => {
1210 var args, index, next, options, queue;
1211 if (this.queued() === 0) {
1212 return this.Promise.resolve(null);
1213 }
1214 queue = this._queues.getFirst();
1215 ({options, args} = next = queue.first());
1216 if ((capacity != null) && options.weight > capacity) {
1217 return this.Promise.resolve(null);
1218 }
1219 this.Events.trigger("debug", `Draining ${options.id}`, {args, options});
1220 index = this._randomIndex();
1221 return this._store.__register__(index, options.weight, options.expiration).then(({success, wait, reservoir}) => {
1222 var empty;
1223 this.Events.trigger("debug", `Drained ${options.id}`, {success, args, options});
1224 if (success) {
1225 queue.shift();
1226 empty = this.empty();
1227 if (empty) {
1228 this.Events.trigger("empty");
1229 }
1230 if (reservoir === 0) {
1231 this.Events.trigger("depleted", empty);
1232 }
1233 this._run(index, next, wait);
1234 return this.Promise.resolve(options.weight);
1235 } else {
1236 return this.Promise.resolve(null);
1237 }
1238 });
1239 });
1240 }
1241
1242 _drainAll(capacity, total = 0) {
1243 return this._drainOne(capacity).then((drained) => {
1244 var newCapacity;
1245 if (drained != null) {
1246 newCapacity = capacity != null ? capacity - drained : capacity;
1247 return this._drainAll(newCapacity, total + drained);
1248 } else {
1249 return this.Promise.resolve(total);
1250 }
1251 }).catch((e) => {
1252 return this.Events.trigger("error", e);
1253 });
1254 }
1255
1256 _dropAllQueued(message) {
1257 return this._queues.shiftAll(function(job) {
1258 return job.doDrop({message});
1259 });
1260 }
1261
1262 stop(options = {}) {
1263 var done, waitForExecuting;
1264 options = parser$5.load(options, this.stopDefaults);
1265 waitForExecuting = (at) => {
1266 var finished;
1267 finished = () => {
1268 var counts;
1269 counts = this._states.counts;
1270 return (counts[0] + counts[1] + counts[2] + counts[3]) === at;
1271 };
1272 return new this.Promise((resolve, reject) => {
1273 if (finished()) {
1274 return resolve();
1275 } else {
1276 return this.on("done", () => {
1277 if (finished()) {
1278 this.removeAllListeners("done");
1279 return resolve();
1280 }
1281 });
1282 }
1283 });
1284 };
1285 done = options.dropWaitingJobs ? (this._run = function(index, next) {
1286 return next.doDrop({
1287 message: options.dropErrorMessage
1288 });
1289 }, this._drainOne = () => {
1290 return this.Promise.resolve(null);
1291 }, this._registerLock.schedule(() => {
1292 return this._submitLock.schedule(() => {
1293 var k, ref, v;
1294 ref = this._scheduled;
1295 for (k in ref) {
1296 v = ref[k];
1297 if (this.jobStatus(v.job.options.id) === "RUNNING") {
1298 clearTimeout(v.timeout);
1299 clearTimeout(v.expiration);
1300 v.job.doDrop({
1301 message: options.dropErrorMessage
1302 });
1303 }
1304 }
1305 this._dropAllQueued(options.dropErrorMessage);
1306 return waitForExecuting(0);
1307 });
1308 })) : this.schedule({
1309 priority: NUM_PRIORITIES$1 - 1,
1310 weight: 0
1311 }, () => {
1312 return waitForExecuting(1);
1313 });
1314 this._receive = function(job) {
1315 return job._reject(new Bottleneck.prototype.BottleneckError(options.enqueueErrorMessage));
1316 };
1317 this.stop = () => {
1318 return this.Promise.reject(new Bottleneck.prototype.BottleneckError("stop() has already been called"));
1319 };
1320 return done;
1321 }
1322
1323 async _addToQueue(job) {
1324 var args, blocked, error, options, reachedHWM, shifted, strategy;
1325 ({args, options} = job);
1326 try {
1327 ({reachedHWM, blocked, strategy} = (await this._store.__submit__(this.queued(), options.weight)));
1328 } catch (error1) {
1329 error = error1;
1330 this.Events.trigger("debug", `Could not queue ${options.id}`, {args, options, error});
1331 job.doDrop({error});
1332 return false;
1333 }
1334 if (blocked) {
1335 job.doDrop();
1336 return true;
1337 } else if (reachedHWM) {
1338 shifted = strategy === Bottleneck.prototype.strategy.LEAK ? this._queues.shiftLastFrom(options.priority) : strategy === Bottleneck.prototype.strategy.OVERFLOW_PRIORITY ? this._queues.shiftLastFrom(options.priority + 1) : strategy === Bottleneck.prototype.strategy.OVERFLOW ? job : void 0;
1339 if (shifted != null) {
1340 shifted.doDrop();
1341 }
1342 if ((shifted == null) || strategy === Bottleneck.prototype.strategy.OVERFLOW) {
1343 if (shifted == null) {
1344 job.doDrop();
1345 }
1346 return reachedHWM;
1347 }
1348 }
1349 job.doQueue(reachedHWM, blocked);
1350 this._queues.push(job);
1351 await this._drainAll();
1352 return reachedHWM;
1353 }
1354
1355 _receive(job) {
1356 if (this._states.jobStatus(job.options.id) != null) {
1357 job._reject(new Bottleneck.prototype.BottleneckError(`A job with the same id already exists (id=${job.options.id})`));
1358 return false;
1359 } else {
1360 job.doReceive();
1361 return this._submitLock.schedule(this._addToQueue, job);
1362 }
1363 }
1364
1365 submit(...args) {
1366 var cb, fn, job, options, ref, ref1, task;
1367 if (typeof args[0] === "function") {
1368 ref = args, [fn, ...args] = ref, [cb] = splice.call(args, -1);
1369 options = parser$5.load({}, this.jobDefaults);
1370 } else {
1371 ref1 = args, [options, fn, ...args] = ref1, [cb] = splice.call(args, -1);
1372 options = parser$5.load(options, this.jobDefaults);
1373 }
1374 task = (...args) => {
1375 return new this.Promise(function(resolve, reject) {
1376 return fn(...args, function(...args) {
1377 return (args[0] != null ? reject : resolve)(args);
1378 });
1379 });
1380 };
1381 job = new Job$1(task, args, options, this.jobDefaults, this.rejectOnDrop, this.Events, this._states, this.Promise);
1382 job.promise.then(function(args) {
1383 return typeof cb === "function" ? cb(...args) : void 0;
1384 }).catch(function(args) {
1385 if (Array.isArray(args)) {
1386 return typeof cb === "function" ? cb(...args) : void 0;
1387 } else {
1388 return typeof cb === "function" ? cb(args) : void 0;
1389 }
1390 });
1391 return this._receive(job);
1392 }
1393
1394 schedule(...args) {
1395 var job, options, task;
1396 if (typeof args[0] === "function") {
1397 [task, ...args] = args;
1398 options = {};
1399 } else {
1400 [options, task, ...args] = args;
1401 }
1402 job = new Job$1(task, args, options, this.jobDefaults, this.rejectOnDrop, this.Events, this._states, this.Promise);
1403 this._receive(job);
1404 return job.promise;
1405 }
1406
1407 wrap(fn) {
1408 var schedule, wrapped;
1409 schedule = this.schedule.bind(this);
1410 wrapped = function(...args) {
1411 return schedule(fn.bind(this), ...args);
1412 };
1413 wrapped.withOptions = function(options, ...args) {
1414 return schedule(options, fn, ...args);
1415 };
1416 return wrapped;
1417 }
1418
1419 async updateSettings(options = {}) {
1420 await this._store.__updateSettings__(parser$5.overwrite(options, this.storeDefaults));
1421 parser$5.overwrite(options, this.instanceDefaults, this);
1422 return this;
1423 }
1424
1425 currentReservoir() {
1426 return this._store.__currentReservoir__();
1427 }
1428
1429 incrementReservoir(incr = 0) {
1430 return this._store.__incrementReservoir__(incr);
1431 }
1432
1433 }
1434 Bottleneck.default = Bottleneck;
1435
1436 Bottleneck.Events = Events$4;
1437
1438 Bottleneck.version = Bottleneck.prototype.version = require$$8.version;
1439
1440 Bottleneck.strategy = Bottleneck.prototype.strategy = {
1441 LEAK: 1,
1442 OVERFLOW: 2,
1443 OVERFLOW_PRIORITY: 4,
1444 BLOCK: 3
1445 };
1446
1447 Bottleneck.BottleneckError = Bottleneck.prototype.BottleneckError = BottleneckError_1;
1448
1449 Bottleneck.Group = Bottleneck.prototype.Group = Group_1;
1450
1451 Bottleneck.RedisConnection = Bottleneck.prototype.RedisConnection = require$$2;
1452
1453 Bottleneck.IORedisConnection = Bottleneck.prototype.IORedisConnection = require$$3;
1454
1455 Bottleneck.Batcher = Bottleneck.prototype.Batcher = Batcher_1;
1456
1457 Bottleneck.prototype.jobDefaults = {
1458 priority: DEFAULT_PRIORITY$1,
1459 weight: 1,
1460 expiration: null,
1461 id: "<no-id>"
1462 };
1463
1464 Bottleneck.prototype.storeDefaults = {
1465 maxConcurrent: null,
1466 minTime: 0,
1467 highWater: null,
1468 strategy: Bottleneck.prototype.strategy.LEAK,
1469 penalty: null,
1470 reservoir: null,
1471 reservoirRefreshInterval: null,
1472 reservoirRefreshAmount: null,
1473 reservoirIncreaseInterval: null,
1474 reservoirIncreaseAmount: null,
1475 reservoirIncreaseMaximum: null
1476 };
1477
1478 Bottleneck.prototype.localStoreDefaults = {
1479 Promise: Promise,
1480 timeout: null,
1481 heartbeatInterval: 250
1482 };
1483
1484 Bottleneck.prototype.redisStoreDefaults = {
1485 Promise: Promise,
1486 timeout: null,
1487 heartbeatInterval: 5000,
1488 clientTimeout: 10000,
1489 Redis: null,
1490 clientOptions: {},
1491 clusterNodes: null,
1492 clearDatastore: false,
1493 connection: null
1494 };
1495
1496 Bottleneck.prototype.instanceDefaults = {
1497 datastore: "local",
1498 connection: null,
1499 id: "<no-id>",
1500 rejectOnDrop: true,
1501 trackDoneStatus: false,
1502 Promise: Promise
1503 };
1504
1505 Bottleneck.prototype.stopDefaults = {
1506 enqueueErrorMessage: "This limiter has been stopped and cannot accept new jobs.",
1507 dropWaitingJobs: true,
1508 dropErrorMessage: "This limiter has been stopped."
1509 };
1510
1511 return Bottleneck;
1512
1513 }).call(commonjsGlobal);
1514
1515 var Bottleneck_1 = Bottleneck;
1516
1517 var lib = Bottleneck_1;
1518
1519 return lib;
1520
1521})));