UNPKG

hsd

Version:
75 lines (60 loc) 1.63 kB
'use strict'; const assert = require('bsert'); const AsyncEmitter = require('bevent'); class SlidingWindow extends AsyncEmitter { /** * Create a sliding window counter * e.g: * ``` * new SlidingWindow({ * window: 1000, * limit: 100 * }) * ``` * creates a sliding window which allows 100 requests per second * @property {Number} window - window period in milliseconds * @property {Number} limit - max requests allowed * @property {Timeout} timeout - sliding window timeout * @property {Number} current - current window counter * @property {Number} previous - previous window counter * @property {Number} timestamp - current window start time in milliseconds */ constructor(options) { super(); this.window = options.window || 1000; this.limit = options.limit || 100; this.timeout = null; this.current = 0; this.previous = 0; this.timestamp = 0; } start() { this.timestamp = Date.now(); this.timeout = setInterval(() => this.reset(), this.window); } stop() { this.timestamp = 0; clearInterval(this.timeout); } async reset() { this.previous = this.current; this.current = 0; this.timestamp = Date.now(); this.emit('reset'); } score() { const ms = Date.now() - this.timestamp; let weight = 1 - (ms / this.window); if (weight < 0) weight = 0; return this.previous * weight + this.current; } increase(count) { assert((count >>> 0) === count); this.current += count; } allow() { return this.score() < this.limit; } } module.exports = SlidingWindow;