@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.
95 lines (93 loc) • 3.56 kB
JavaScript
/**
* @module RateLimiter
*/
import {} from "ioredis";
import { BACKOFFS, resolveBackoffSettingsEnum, serializeBackoffSettingsEnum, } from "../../../../backoff-policies/_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, backoff = {
type: BACKOFFS.EXPONENTIAL,
}, policy = {
type: LIMITER_POLICIES.FIXED_WINDOW,
}, } = settings;
this.database = database;
this.backoff = resolveBackoffSettingsEnum(backoff);
this.policy = resolveRateLimiterPolicySettings(policy);
this.initUpdateStateCommmand();
}
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(key) {
const json = await this.database.get(key);
if (json === null) {
return null;
}
const state = JSON.parse(json);
return {
success: state.success,
attempt: state.attempt,
resetTime: state.resetTime === -1
? null
: TimeSpan.fromDateRange({
end: new Date(state.resetTime),
}),
};
}
async updateState(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: state.resetTime === -1
? null
: TimeSpan.fromDateRange({
end: new Date(state.resetTime),
}),
};
}
async reset(key) {
await this.database.del(key);
}
}
//# sourceMappingURL=redis-rate-limiter-adapter.js.map