UNPKG

@daiso-tech/core

Version:

The library offers flexible, framework-agnostic solutions for modern web applications, built on adaptable components that integrate seamlessly with popular frameworks like Next Js.

113 lines (109 loc) 4.48 kB
/** * @module RateLimiter */ import {} from "ioredis"; import { BACKOFFS, resolveBackoffSettingsEnum, serializeBackoffSettingsEnum, } from "../../../../backoff-policies/implementations/_module.js"; import {} from "../../../../execution-context/contracts/_module.js"; import {} from "../../../../rate-limiter/contracts/_module.js"; import { rateLimiterFactoryLua } from "../../../../rate-limiter/implementations/adapters/redis-rate-limiter-adapter/lua/_module.js"; import { LIMITER_POLICIES, resolveRateLimiterPolicySettings, serializeRateLimiterPolicySettingsEnum, } from "../../../../rate-limiter/implementations/policies/_module.js"; import { TimeSpan } from "../../../../time-span/implementations/time-span.js"; /** * IMPORT_PATH: `"@daiso-tech/core/rate-limiter/redis-rate-limiter-adapter"` * @group Adapters */ export class RedisRateLimiterAdapter { backoff; policy; database; /** * @example * ```ts * import { RedisRateLimiterAdapter } from "@daiso-tech/core/rate-limiter/redis-rate-limiter-adapter"; * import Redis from "ioredis"; * * const database = new Redis("YOUR_REDIS_CONNECTION_STRING"); * const rateLimiterAdapter = new RedisRateLimiterAdapter({ * database * }); * ``` */ constructor(settings) { const { database, backoffPolicy = { type: BACKOFFS.EXPONENTIAL, }, rateLimiterPolicy = { type: LIMITER_POLICIES.FIXED_WINDOW, }, } = settings; this.database = database; this.backoff = resolveBackoffSettingsEnum(backoffPolicy); this.policy = resolveRateLimiterPolicySettings(rateLimiterPolicy); this.initGetStateCommand(); this.initUpdateStateCommmand(); } initGetStateCommand() { if (typeof this.database.daiso_rate_limiter_get_state === "function") { return; } this.database.defineCommand("daiso_rate_limiter_get_state", { numberOfKeys: 1, lua: ` ${rateLimiterFactoryLua} local key = KEYS[1]; local backoffSettings = cjson.decode(ARGV[1]); local policySettings = cjson.decode(ARGV[2]); local currentDate = tonumber(ARGV[3]); local rateLimiter = rateLimiterFactory(backoffSettings, policySettings, currentDate) local state = rateLimiter.getState(key) return cjson.encode(state) `, }); } initUpdateStateCommmand() { if (typeof this.database.daiso_rate_limiter_update_state === "function") { return; } this.database.defineCommand("daiso_rate_limiter_update_state", { numberOfKeys: 1, lua: ` ${rateLimiterFactoryLua} local key = KEYS[1]; local limit = tonumber(ARGV[1]); local backoffSettings = cjson.decode(ARGV[2]); local policySettings = cjson.decode(ARGV[3]); local currentDate = tonumber(ARGV[4]); local rateLimiter = rateLimiterFactory(backoffSettings, policySettings, currentDate) local state = rateLimiter.updateState(key, limit) return cjson.encode(state) `, }); } async getState(_context, key) { const json = await this.database.daiso_rate_limiter_get_state(key, JSON.stringify(serializeBackoffSettingsEnum(this.backoff)), JSON.stringify(serializeRateLimiterPolicySettingsEnum(this.policy)), Date.now()); const state = JSON.parse(json); if (state === null) { return null; } return { success: state.success, attempt: state.attempt, resetTime: TimeSpan.fromDateRange({ end: new Date(state.resetTime), }), }; } async updateState(_context, key, limit) { const json = await this.database.daiso_rate_limiter_update_state(key, limit, JSON.stringify(serializeBackoffSettingsEnum(this.backoff)), JSON.stringify(serializeRateLimiterPolicySettingsEnum(this.policy)), Date.now()); const state = JSON.parse(json); return { success: state.success, attempt: state.attempt, resetTime: TimeSpan.fromDateRange({ end: new Date(state.resetTime), }), }; } async reset(_context, key) { await this.database.del(key); } } //# sourceMappingURL=redis-rate-limiter-adapter.js.map