@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.
59 lines • 2.21 kB
JavaScript
/**
* @module RateLimiter
*/
import {} from "../../../../backoff-policies/_module.js";
import { RATE_LIMITER_STATE, } from "../../../../rate-limiter/contracts/_module.js";
import {} from "../../../../rate-limiter/implementations/adapters/database-rate-limiter-adapter/rate-limiter-policy.js";
import { TimeSpan } from "../../../../time-span/implementations/time-span.js";
import { callInvokable } from "../../../../utilities/_module.js";
/**
* @internal
*/
export class RateLimiterStorage {
adapter;
rateLimiterPolicy;
backoffPolicy;
constructor(settings) {
const { adapter, rateLimiterPolicy, backoffPolicy } = settings;
this.adapter = adapter;
this.rateLimiterPolicy = rateLimiterPolicy;
this.backoffPolicy = backoffPolicy;
}
async atomicUpdate(args) {
const currentDate = new Date();
const state = await this.adapter.transaction(async (trx) => {
const data = await this.adapter.find(args.key);
let currentState = data?.state;
if (currentState === undefined) {
currentState = this.rateLimiterPolicy.initialState(currentDate);
}
const newState = args.update(currentState);
await trx.upsert(args.key, newState, this.rateLimiterPolicy.getExpiration(newState, {
backoffPolicy: this.backoffPolicy,
currentDate,
}));
return newState;
});
return this.toAdapterState(state);
}
toAdapterState(state) {
return {
success: state.type === RATE_LIMITER_STATE.ALLOWED,
attempt: state.attempt,
resetTime: state.type === RATE_LIMITER_STATE.ALLOWED
? null
: TimeSpan.fromTimeSpan(callInvokable(this.backoffPolicy, state.attempt, null)).toEndDate(new Date(state.startedAt)),
};
}
async find(key) {
const data = await this.adapter.find(key);
if (data === null) {
return null;
}
return this.toAdapterState(data.state);
}
async remove(key) {
await this.adapter.remove(key);
}
}
//# sourceMappingURL=rate-limiter-storage.js.map