initial commit
This commit is contained in:
163
node_modules/async-sema/lib/index.js
generated
vendored
Normal file
163
node_modules/async-sema/lib/index.js
generated
vendored
Normal file
@@ -0,0 +1,163 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.RateLimit = exports.Sema = void 0;
|
||||
const events_1 = __importDefault(require("events"));
|
||||
function arrayMove(src, srcIndex, dst, dstIndex, len) {
|
||||
for (let j = 0; j < len; ++j) {
|
||||
dst[j + dstIndex] = src[j + srcIndex];
|
||||
src[j + srcIndex] = void 0;
|
||||
}
|
||||
}
|
||||
function pow2AtLeast(n) {
|
||||
n = n >>> 0;
|
||||
n = n - 1;
|
||||
n = n | (n >> 1);
|
||||
n = n | (n >> 2);
|
||||
n = n | (n >> 4);
|
||||
n = n | (n >> 8);
|
||||
n = n | (n >> 16);
|
||||
return n + 1;
|
||||
}
|
||||
function getCapacity(capacity) {
|
||||
return pow2AtLeast(Math.min(Math.max(16, capacity), 1073741824));
|
||||
}
|
||||
// Deque is based on https://github.com/petkaantonov/deque/blob/master/js/deque.js
|
||||
// Released under the MIT License: https://github.com/petkaantonov/deque/blob/6ef4b6400ad3ba82853fdcc6531a38eb4f78c18c/LICENSE
|
||||
class Deque {
|
||||
constructor(capacity) {
|
||||
this._capacity = getCapacity(capacity);
|
||||
this._length = 0;
|
||||
this._front = 0;
|
||||
this.arr = [];
|
||||
}
|
||||
push(item) {
|
||||
const length = this._length;
|
||||
this.checkCapacity(length + 1);
|
||||
const i = (this._front + length) & (this._capacity - 1);
|
||||
this.arr[i] = item;
|
||||
this._length = length + 1;
|
||||
return length + 1;
|
||||
}
|
||||
pop() {
|
||||
const length = this._length;
|
||||
if (length === 0) {
|
||||
return void 0;
|
||||
}
|
||||
const i = (this._front + length - 1) & (this._capacity - 1);
|
||||
const ret = this.arr[i];
|
||||
this.arr[i] = void 0;
|
||||
this._length = length - 1;
|
||||
return ret;
|
||||
}
|
||||
shift() {
|
||||
const length = this._length;
|
||||
if (length === 0) {
|
||||
return void 0;
|
||||
}
|
||||
const front = this._front;
|
||||
const ret = this.arr[front];
|
||||
this.arr[front] = void 0;
|
||||
this._front = (front + 1) & (this._capacity - 1);
|
||||
this._length = length - 1;
|
||||
return ret;
|
||||
}
|
||||
get length() {
|
||||
return this._length;
|
||||
}
|
||||
checkCapacity(size) {
|
||||
if (this._capacity < size) {
|
||||
this.resizeTo(getCapacity(this._capacity * 1.5 + 16));
|
||||
}
|
||||
}
|
||||
resizeTo(capacity) {
|
||||
const oldCapacity = this._capacity;
|
||||
this._capacity = capacity;
|
||||
const front = this._front;
|
||||
const length = this._length;
|
||||
if (front + length > oldCapacity) {
|
||||
const moveItemsCount = (front + length) & (oldCapacity - 1);
|
||||
arrayMove(this.arr, 0, this.arr, oldCapacity, moveItemsCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
class ReleaseEmitter extends events_1.default {
|
||||
}
|
||||
function isFn(x) {
|
||||
return typeof x === 'function';
|
||||
}
|
||||
function defaultInit() {
|
||||
return '1';
|
||||
}
|
||||
class Sema {
|
||||
constructor(nr, { initFn = defaultInit, pauseFn, resumeFn, capacity = 10, } = {}) {
|
||||
if (isFn(pauseFn) !== isFn(resumeFn)) {
|
||||
throw new Error('pauseFn and resumeFn must be both set for pausing');
|
||||
}
|
||||
this.nrTokens = nr;
|
||||
this.free = new Deque(nr);
|
||||
this.waiting = new Deque(capacity);
|
||||
this.releaseEmitter = new ReleaseEmitter();
|
||||
this.noTokens = initFn === defaultInit;
|
||||
this.pauseFn = pauseFn;
|
||||
this.resumeFn = resumeFn;
|
||||
this.paused = false;
|
||||
this.releaseEmitter.on('release', (token) => {
|
||||
const p = this.waiting.shift();
|
||||
if (p) {
|
||||
p.resolve(token);
|
||||
}
|
||||
else {
|
||||
if (this.resumeFn && this.paused) {
|
||||
this.paused = false;
|
||||
this.resumeFn();
|
||||
}
|
||||
this.free.push(token);
|
||||
}
|
||||
});
|
||||
for (let i = 0; i < nr; i++) {
|
||||
this.free.push(initFn());
|
||||
}
|
||||
}
|
||||
tryAcquire() {
|
||||
return this.free.pop();
|
||||
}
|
||||
async acquire() {
|
||||
let token = this.tryAcquire();
|
||||
if (token !== void 0) {
|
||||
return token;
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
if (this.pauseFn && !this.paused) {
|
||||
this.paused = true;
|
||||
this.pauseFn();
|
||||
}
|
||||
this.waiting.push({ resolve, reject });
|
||||
});
|
||||
}
|
||||
release(token) {
|
||||
this.releaseEmitter.emit('release', this.noTokens ? '1' : token);
|
||||
}
|
||||
drain() {
|
||||
const a = new Array(this.nrTokens);
|
||||
for (let i = 0; i < this.nrTokens; i++) {
|
||||
a[i] = this.acquire();
|
||||
}
|
||||
return Promise.all(a);
|
||||
}
|
||||
nrWaiting() {
|
||||
return this.waiting.length;
|
||||
}
|
||||
}
|
||||
exports.Sema = Sema;
|
||||
function RateLimit(rps, { timeUnit = 1000, uniformDistribution = false, } = {}) {
|
||||
const sema = new Sema(uniformDistribution ? 1 : rps);
|
||||
const delay = uniformDistribution ? timeUnit / rps : timeUnit;
|
||||
return async function rl() {
|
||||
await sema.acquire();
|
||||
setTimeout(() => sema.release(), delay);
|
||||
};
|
||||
}
|
||||
exports.RateLimit = RateLimit;
|
||||
Reference in New Issue
Block a user