File size: 1,460 Bytes
9438a57 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | /**
* Jeton kovası (token bucket) hız sınırlayıcı. Saat dışarıdan verilir (test edilebilirlik).
* Kova en fazla `capacity` jeton tutar ve saniyede `refillPerSec` jeton dolar.
*/
class RateLimiter {
constructor({ capacity, refillPerSec, now = () => Date.now() }) {
if (!(capacity > 0)) throw new RangeError('capacity pozitif olmalı');
if (!(refillPerSec >= 0)) throw new RangeError('refillPerSec negatif olamaz');
this.capacity = capacity;
this.refillPerSec = refillPerSec;
this.now = now;
this.tokens = capacity;
this.last = now();
}
_refill() {
const t = this.now();
const elapsed = (t - this.last) / 1000;
if (elapsed > 0) {
this.tokens = Math.min(this.capacity, this.tokens + elapsed * this.refillPerSec);
this.last = t;
}
}
/** Yeterli jeton varsa harcar ve true döner; yoksa hiçbir şey harcamadan false. */
tryRemove(cost = 1) {
if (cost <= 0) throw new RangeError('cost pozitif olmalı');
this._refill();
if (this.tokens >= cost) {
this.tokens -= cost;
return true;
}
return false;
}
/** Bir sonraki `cost` jetonluk istek için beklenmesi gereken süre (ms, yukarı yuvarlanmış). */
waitTime(cost = 1) {
this._refill();
if (this.tokens >= cost) return 0;
if (this.refillPerSec === 0) return Infinity;
return Math.ceil(((cost - this.tokens) / this.refillPerSec) * 1000);
}
}
module.exports = { RateLimiter };
|