@d-fischer/rate-limiter
Advanced tools
Comparing version 0.7.0 to 0.7.1
@@ -0,0 +0,0 @@ /** @private */ |
@@ -0,0 +0,0 @@ "use strict"; |
import { CustomError } from './CustomError'; | ||
export declare class RateLimitReachedError extends CustomError { | ||
} |
@@ -0,0 +0,0 @@ "use strict"; |
@@ -0,0 +0,0 @@ import { CustomError } from './CustomError'; |
@@ -0,0 +0,0 @@ "use strict"; |
@@ -0,0 +0,0 @@ export type { QueueEntryLimitReachedBehavior } from './QueueEntry'; |
@@ -0,0 +0,0 @@ "use strict"; |
@@ -6,2 +6,5 @@ import type { RateLimiter } from '../RateLimiter'; | ||
request(req: Req): Promise<Res>; | ||
clear(): void; | ||
pause(): void; | ||
resume(): void; | ||
} |
@@ -19,2 +19,11 @@ "use strict"; | ||
}; | ||
NullRateLimiter.prototype.clear = function () { | ||
// noop | ||
}; | ||
NullRateLimiter.prototype.pause = function () { | ||
// noop | ||
}; | ||
NullRateLimiter.prototype.resume = function () { | ||
// noop | ||
}; | ||
return NullRateLimiter; | ||
@@ -21,0 +30,0 @@ }()); |
@@ -11,6 +11,10 @@ import { type RateLimiter, type RateLimiterRequestOptions } from '../RateLimiter'; | ||
private readonly _createChildCallback; | ||
private _paused; | ||
constructor(options: PartitionedRateLimiterOptions<Req, Res>); | ||
request(req: Req, options?: RateLimiterRequestOptions): Promise<Res>; | ||
clear(): void; | ||
pause(): void; | ||
resume(): void; | ||
getChildStats(partitionKey: string | null): RateLimiterStats | null; | ||
private _getChild; | ||
} |
@@ -9,2 +9,3 @@ "use strict"; | ||
this._children = new Map(); | ||
this._paused = false; | ||
this._partitionKeyCallback = options.getPartitionKey; | ||
@@ -27,2 +28,52 @@ this._createChildCallback = options.createChild; | ||
}; | ||
PartitionedRateLimiter.prototype.clear = function () { | ||
var e_1, _a; | ||
try { | ||
for (var _b = tslib_1.__values(this._children.values()), _c = _b.next(); !_c.done; _c = _b.next()) { | ||
var child = _c.value; | ||
child.clear(); | ||
} | ||
} | ||
catch (e_1_1) { e_1 = { error: e_1_1 }; } | ||
finally { | ||
try { | ||
if (_c && !_c.done && (_a = _b.return)) _a.call(_b); | ||
} | ||
finally { if (e_1) throw e_1.error; } | ||
} | ||
}; | ||
PartitionedRateLimiter.prototype.pause = function () { | ||
var e_2, _a; | ||
this._paused = true; | ||
try { | ||
for (var _b = tslib_1.__values(this._children.values()), _c = _b.next(); !_c.done; _c = _b.next()) { | ||
var child = _c.value; | ||
child.pause(); | ||
} | ||
} | ||
catch (e_2_1) { e_2 = { error: e_2_1 }; } | ||
finally { | ||
try { | ||
if (_c && !_c.done && (_a = _b.return)) _a.call(_b); | ||
} | ||
finally { if (e_2) throw e_2.error; } | ||
} | ||
}; | ||
PartitionedRateLimiter.prototype.resume = function () { | ||
var e_3, _a; | ||
this._paused = false; | ||
try { | ||
for (var _b = tslib_1.__values(this._children.values()), _c = _b.next(); !_c.done; _c = _b.next()) { | ||
var child = _c.value; | ||
child.resume(); | ||
} | ||
} | ||
catch (e_3_1) { e_3 = { error: e_3_1 }; } | ||
finally { | ||
try { | ||
if (_c && !_c.done && (_a = _b.return)) _a.call(_b); | ||
} | ||
finally { if (e_3) throw e_3.error; } | ||
} | ||
}; | ||
PartitionedRateLimiter.prototype.getChildStats = function (partitionKey) { | ||
@@ -43,2 +94,5 @@ if (!this._children.has(partitionKey)) { | ||
var result = this._createChildCallback(partitionKey); | ||
if (this._paused) { | ||
result.pause(); | ||
} | ||
this._children.set(partitionKey, result); | ||
@@ -45,0 +99,0 @@ return result; |
@@ -13,5 +13,9 @@ import type { RateLimiter, RateLimiterRequestOptions } from '../RateLimiter'; | ||
private readonly _partitionKeyCallback; | ||
private _paused; | ||
private readonly _logger; | ||
constructor({ logger, bucketSize, timeFrame, doRequest, getPartitionKey }: PartitionedTimeBasedRateLimiterConfig<Req, Res>); | ||
request(req: Req, options?: RateLimiterRequestOptions): Promise<Res>; | ||
clear(): void; | ||
pause(): void; | ||
resume(): void; | ||
private _getPartitionedQueue; | ||
@@ -18,0 +22,0 @@ private _runRequest; |
@@ -12,2 +12,3 @@ "use strict"; | ||
this._usedFromBucket = new Map(); | ||
this._paused = false; | ||
this._logger = (0, logger_1.createLogger)(tslib_1.__assign({ name: 'rate-limiter', emoji: true }, logger)); | ||
@@ -34,3 +35,3 @@ this._bucketSize = bucketSize; | ||
var usedFromBucket = (_b = _this._usedFromBucket.get(partitionKey)) !== null && _b !== void 0 ? _b : 0; | ||
if (usedFromBucket >= _this._bucketSize) { | ||
if (usedFromBucket >= _this._bucketSize || _this._paused) { | ||
switch (reqSpec.limitReachedBehavior) { | ||
@@ -66,2 +67,25 @@ case 'enqueue': { | ||
}; | ||
PartitionedTimeBasedRateLimiter.prototype.clear = function () { | ||
this._partitionedQueue.clear(); | ||
}; | ||
PartitionedTimeBasedRateLimiter.prototype.pause = function () { | ||
this._paused = true; | ||
}; | ||
PartitionedTimeBasedRateLimiter.prototype.resume = function () { | ||
var e_1, _a; | ||
this._paused = false; | ||
try { | ||
for (var _b = tslib_1.__values(this._partitionedQueue.keys()), _c = _b.next(); !_c.done; _c = _b.next()) { | ||
var partitionKey = _c.value; | ||
this._runNextRequest(partitionKey); | ||
} | ||
} | ||
catch (e_1_1) { e_1 = { error: e_1_1 }; } | ||
finally { | ||
try { | ||
if (_c && !_c.done && (_a = _b.return)) _a.call(_b); | ||
} | ||
finally { if (e_1) throw e_1.error; } | ||
} | ||
}; | ||
PartitionedTimeBasedRateLimiter.prototype._getPartitionedQueue = function (partitionKey) { | ||
@@ -78,3 +102,3 @@ if (this._partitionedQueue.has(partitionKey)) { | ||
return tslib_1.__awaiter(this, void 0, void 0, function () { | ||
var queue, req, resolve, reject, _b, e_1; | ||
var queue, req, resolve, reject, _b, e_2; | ||
var _this = this; | ||
@@ -97,4 +121,4 @@ return tslib_1.__generator(this, function (_c) { | ||
case 3: | ||
e_1 = _c.sent(); | ||
reject(e_1); | ||
e_2 = _c.sent(); | ||
reject(e_2); | ||
return [3 /*break*/, 5]; | ||
@@ -116,2 +140,5 @@ case 4: | ||
PartitionedTimeBasedRateLimiter.prototype._runNextRequest = function (partitionKey) { | ||
if (this._paused) { | ||
return; | ||
} | ||
var queue = this._getPartitionedQueue(partitionKey); | ||
@@ -118,0 +145,0 @@ var reqSpec = queue.shift(); |
@@ -17,5 +17,9 @@ import type { LoggerOptions } from '@d-fischer/logger'; | ||
private _nextBatchTimer?; | ||
private _paused; | ||
private readonly _logger; | ||
constructor({ logger }: ResponseBasedRateLimiterConfig); | ||
request(req: Req, options?: RateLimiterRequestOptions): Promise<Res>; | ||
clear(): void; | ||
pause(): void; | ||
resume(): void; | ||
get stats(): RateLimiterStats; | ||
@@ -22,0 +26,0 @@ protected abstract doRequest(req: Req): Promise<Res>; |
@@ -15,2 +15,3 @@ "use strict"; | ||
this._batchRunning = false; | ||
this._paused = false; | ||
this._logger = (0, logger_1.createLogger)(tslib_1.__assign({ name: 'rate-limiter', emoji: true }, logger)); | ||
@@ -33,5 +34,5 @@ } | ||
}; | ||
if (_this._batchRunning || _this._nextBatchTimer) { | ||
if (_this._batchRunning || _this._nextBatchTimer || _this._paused) { | ||
_this._logger.trace("request queued batchRunning:".concat(_this._batchRunning.toString(), " hasNextBatchTimer:").concat((!!_this | ||
._nextBatchTimer).toString())); | ||
._nextBatchTimer).toString(), " paused:").concat(_this._paused.toString())); | ||
_this._queue.push(reqSpec); | ||
@@ -48,2 +49,12 @@ } | ||
}; | ||
ResponseBasedRateLimiter.prototype.clear = function () { | ||
this._queue = []; | ||
}; | ||
ResponseBasedRateLimiter.prototype.pause = function () { | ||
this._paused = true; | ||
}; | ||
ResponseBasedRateLimiter.prototype.resume = function () { | ||
this._paused = false; | ||
this._runNextBatch(); | ||
}; | ||
Object.defineProperty(ResponseBasedRateLimiter.prototype, "stats", { | ||
@@ -118,3 +129,3 @@ get: function () { | ||
_this._parameters = undefined; | ||
void _this._runNextBatch(); | ||
_this._runNextBatch(); | ||
}, retryAfter); | ||
@@ -141,3 +152,3 @@ } | ||
this._logger.trace('runRequestBatch canRunMore'); | ||
void this._runNextBatch(); | ||
this._runNextBatch(); | ||
} | ||
@@ -168,3 +179,3 @@ else { | ||
_this._parameters = undefined; | ||
void _this._runNextBatch(); | ||
_this._runNextBatch(); | ||
}, delay); | ||
@@ -181,19 +192,16 @@ } | ||
ResponseBasedRateLimiter.prototype._runNextBatch = function () { | ||
return tslib_1.__awaiter(this, void 0, void 0, function () { | ||
var amount, reqSpecs; | ||
return tslib_1.__generator(this, function (_a) { | ||
this._logger.trace('runNextBatch start'); | ||
if (this._nextBatchTimer) { | ||
clearTimeout(this._nextBatchTimer); | ||
this._nextBatchTimer = undefined; | ||
} | ||
amount = this._parameters ? Math.min(this._parameters.remaining, this._parameters.limit / 10) : 1; | ||
reqSpecs = this._queue.splice(0, amount); | ||
if (reqSpecs.length) { | ||
void this._runRequestBatch(reqSpecs); | ||
} | ||
this._logger.trace('runNextBatch end'); | ||
return [2 /*return*/]; | ||
}); | ||
}); | ||
if (this._paused) { | ||
return; | ||
} | ||
this._logger.trace('runNextBatch start'); | ||
if (this._nextBatchTimer) { | ||
clearTimeout(this._nextBatchTimer); | ||
this._nextBatchTimer = undefined; | ||
} | ||
var amount = this._parameters ? Math.min(this._parameters.remaining, this._parameters.limit / 10) : 1; | ||
var reqSpecs = this._queue.splice(0, amount); | ||
if (reqSpecs.length) { | ||
void this._runRequestBatch(reqSpecs); | ||
} | ||
this._logger.trace('runNextBatch end'); | ||
}; | ||
@@ -200,0 +208,0 @@ return ResponseBasedRateLimiter; |
@@ -10,3 +10,3 @@ import type { LoggerOptions } from '@d-fischer/logger'; | ||
export declare class TimeBasedRateLimiter<Req, Res> implements RateLimiter<Req, Res> { | ||
private readonly _queue; | ||
private _queue; | ||
private _usedFromBucket; | ||
@@ -16,7 +16,11 @@ private readonly _bucketSize; | ||
private readonly _callback; | ||
private _paused; | ||
private readonly _logger; | ||
constructor({ logger, bucketSize, timeFrame, doRequest }: TimeBasedRateLimiterConfig<Req, Res>); | ||
request(req: Req, options?: RateLimiterRequestOptions): Promise<Res>; | ||
clear(): void; | ||
pause(): void; | ||
resume(): void; | ||
private _runRequest; | ||
private _runNextRequest; | ||
} |
@@ -12,2 +12,3 @@ "use strict"; | ||
this._usedFromBucket = 0; | ||
this._paused = false; | ||
this._logger = (0, logger_1.createLogger)(tslib_1.__assign({ name: 'rate-limiter', emoji: true }, logger)); | ||
@@ -31,3 +32,3 @@ this._bucketSize = bucketSize; | ||
}; | ||
if (_this._usedFromBucket >= _this._bucketSize) { | ||
if (_this._usedFromBucket >= _this._bucketSize || _this._paused) { | ||
switch (reqSpec.limitReachedBehavior) { | ||
@@ -62,2 +63,12 @@ case 'enqueue': { | ||
}; | ||
TimeBasedRateLimiter.prototype.clear = function () { | ||
this._queue = []; | ||
}; | ||
TimeBasedRateLimiter.prototype.pause = function () { | ||
this._paused = true; | ||
}; | ||
TimeBasedRateLimiter.prototype.resume = function () { | ||
this._paused = false; | ||
this._runNextRequest(); | ||
}; | ||
TimeBasedRateLimiter.prototype._runRequest = function (reqSpec) { | ||
@@ -99,2 +110,5 @@ return tslib_1.__awaiter(this, void 0, void 0, function () { | ||
TimeBasedRateLimiter.prototype._runNextRequest = function () { | ||
if (this._paused) { | ||
return; | ||
} | ||
var reqSpec = this._queue.shift(); | ||
@@ -101,0 +115,0 @@ if (reqSpec) { |
@@ -0,0 +0,0 @@ import type { RateLimiter } from '../RateLimiter'; |
@@ -0,0 +0,0 @@ "use strict"; |
@@ -0,0 +0,0 @@ export type QueueEntryLimitReachedBehavior = 'enqueue' | 'throw' | 'null'; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
//# sourceMappingURL=QueueEntry.js.map |
@@ -7,2 +7,5 @@ import type { QueueEntryLimitReachedBehavior } from './QueueEntry'; | ||
request: (req: Req, options?: RateLimiterRequestOptions) => Promise<Res>; | ||
clear: () => void; | ||
pause: () => void; | ||
resume: () => void; | ||
} |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
//# sourceMappingURL=RateLimiter.js.map |
@@ -0,0 +0,0 @@ export interface RateLimiterStats { |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
//# sourceMappingURL=RateLimiterStats.js.map |
{ | ||
"name": "@d-fischer/rate-limiter", | ||
"version": "0.7.0", | ||
"version": "0.7.1", | ||
"description": "Rate limit your requests.", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
114654
67
1539