mirror of
https://github.com/Cameri/nostream.git
synced 2025-08-03 19:22:12 +02:00
feat: add sliding window rate limiter
This commit is contained in:
8
src/@types/utils.ts
Normal file
8
src/@types/utils.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
export interface IRateLimiterOptions {
|
||||||
|
period: number;
|
||||||
|
rate: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IRateLimiter {
|
||||||
|
hit(key: string, step: number, options: IRateLimiterOptions): Promise<boolean>
|
||||||
|
}
|
35
src/utils/sliding-window-rate-limiter.ts
Normal file
35
src/utils/sliding-window-rate-limiter.ts
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import { IRateLimiter, IRateLimiterOptions } from '../@types/utils'
|
||||||
|
import { createLogger } from '../factories/logger-factory'
|
||||||
|
import { ICacheAdapter } from '../@types/adapters'
|
||||||
|
|
||||||
|
const debug = createLogger('sliding-window-rate-limiter')
|
||||||
|
|
||||||
|
export class SlidingWindowRateLimiter implements IRateLimiter {
|
||||||
|
public constructor(
|
||||||
|
private readonly cache: ICacheAdapter,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public async hit(
|
||||||
|
key: string,
|
||||||
|
step: number,
|
||||||
|
options: IRateLimiterOptions,
|
||||||
|
): Promise<boolean> {
|
||||||
|
const timestamp = Date.now()
|
||||||
|
const { period } = options
|
||||||
|
|
||||||
|
debug('add %d hits on %s bucket', step, key)
|
||||||
|
|
||||||
|
const [,, entries] = await Promise.all([
|
||||||
|
this.cache.removeRangeByScoreFromSortedSet(key, 0, timestamp - period),
|
||||||
|
this.cache.addToSortedSet(key, { [`${timestamp}:${step}`]: timestamp.toString() }),
|
||||||
|
this.cache.getRangeFromSortedSet(key, 0, -1),
|
||||||
|
this.cache.setKeyExpiry(key, period),
|
||||||
|
])
|
||||||
|
|
||||||
|
const hits = entries.reduce((acc, timestampAndStep) => acc + Number(timestampAndStep.split(':')[1]), 0)
|
||||||
|
|
||||||
|
debug('hit count on %s bucket: %d', key, hits)
|
||||||
|
|
||||||
|
return hits > options.rate
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user