UNPKG

redis-sliding-rate-limiter

Version:

Flexible and performant rate limiter based on sliding window algorithm with arbitrary precision

67 lines (66 loc) 2.82 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.RedisStrategy = void 0; const Strategy_1 = require("./Strategy"); const lua_1 = require("../lua"); class RedisStrategy extends Strategy_1.Strategy { sendCommand(cmd, ...args) { return __awaiter(this, void 0, void 0, function* () { return yield this.limiter.client.sendCommand([cmd, ...args]); }); } loadScript() { return __awaiter(this, void 0, void 0, function* () { return yield this.sendCommand('SCRIPT', 'LOAD', lua_1.LuaScript); }); } execScript(key) { return __awaiter(this, void 0, void 0, function* () { if (!this.scriptSha1) { this.scriptSha1 = yield this.loadScript(); } // NB: redis library sendCommand function accepts arguments only as string or Buffer const args = [ this.scriptSha1, '1', // number of keys `${key}`, `${this.limiter.window}`, `${lua_1.MicrosecondsToWindowSubdivision[this.limiter.windowSubdivisionUnit]}`, `${this.limiter.windowExpireMs}`, `${this.limiter.limit}`, `${this.limiter.limitOverhead}` ]; let res; try { res = yield this.sendCommand('EVALSHA', ...args); } catch (err) { // Script expired in Redis cache, reload and try again if (err && err.message && err.message.includes('NOSCRIPT')) { this.scriptSha1 = yield this.loadScript(); args[0] = this.scriptSha1; res = yield this.sendCommand('EVALSHA', ...args); } else { throw err; } } return { allowed: !!res[0], remaining: Math.max(0, res[1]), firstExpireAtMs: res[2], windowExpireAtMs: res[3] }; }); } } exports.RedisStrategy = RedisStrategy;