import { IRateLimitResult } from '../../../shared/types'; /** * Pure, time-injected implementations of the three rate limit algorithms for * the in-memory store. Result parity contract: for the same inputs these * functions produce exactly what the Lua scripts + the Redis adapter's * parse helpers produce — including rounding and the `retryAfter` * 0 -> undefined mapping. `now` is always epoch milliseconds. */ export interface IFixedWindowEntry { kind: 'fixed'; /** Window start, epoch seconds. */ window: number; count: number; /** Epoch ms after which the entry is dead (sweep/lazy-expiry boundary). */ expiresAt: number; } export interface ISlidingWindowEntry { kind: 'sliding'; /** Epoch ms of each allowed request, oldest first. */ timestamps: number[]; expiresAt: number; } export interface ITokenBucketEntry { kind: 'bucket'; tokens: number; /** Epoch ms of the last refill computation. */ lastRefill: number; expiresAt: number; } export type IMemoryRateLimitEntry = IFixedWindowEntry | ISlidingWindowEntry | ITokenBucketEntry; /** * True when the entry has outlived its retention window and must be treated * as absent (the in-memory equivalent of Redis key expiry). */ export declare function isEntryExpired(entry: IMemoryRateLimitEntry, now: number): boolean; /** * Fixed window: counter per aligned window. Lua parity: the counter keeps * incrementing on rejects (INCR runs unconditionally). */ export declare function applyFixedWindow(entry: IMemoryRateLimitEntry | undefined, now: number, points: number, duration: number): { entry: IFixedWindowEntry; result: IRateLimitResult; }; /** * Sliding window log. Lua parity: entries with score <= now - duration are * pruned (inclusive boundary), rejected requests are NOT recorded, and the * expiry is refreshed only on allow (PEXPIRE lives in the allow branch). */ export declare function applySlidingWindow(entry: IMemoryRateLimitEntry | undefined, now: number, points: number, duration: number): { entry: ISlidingWindowEntry; result: IRateLimitResult; }; /** * Token bucket. Lua parity: state is persisted on BOTH branches (reject still * stores the refilled tokens and stamps lastRefill), `current` is the floored * pre-consume token count, and retention mirrors * PEXPIRE ceil(capacity / refillRate * 1000) + 1000. */ export declare function applyTokenBucket(entry: IMemoryRateLimitEntry | undefined, now: number, capacity: number, refillRate: number, consume?: number): { entry: ITokenBucketEntry; result: IRateLimitResult; }; /** * Peek parity with RedisRateLimitStoreAdapter.peek: fixed window uses strict * `<` for allowed, sliding window resets at floor(now/1000) + duration, and * token bucket reports `current` as capacity - remaining. */ export declare function peekFixedWindow(entry: IMemoryRateLimitEntry | undefined, now: number, points: number, duration: number): IRateLimitResult; export declare function peekSlidingWindow(entry: IMemoryRateLimitEntry | undefined, now: number, points: number, duration: number): IRateLimitResult; export declare function peekTokenBucket(entry: IMemoryRateLimitEntry | undefined, now: number, capacity: number, refillRate: number): IRateLimitResult; //# sourceMappingURL=in-memory-algorithms.d.ts.map