Add rolling rate limiter

This commit is contained in:
Jonas L
2018-05-09 15:20:01 +02:00
parent e199aed403
commit 449a5e2d87
4 changed files with 98 additions and 0 deletions
+38
View File
@@ -0,0 +1,38 @@
// Type definitions for rolling-rate-limiter 0.1
// Project: https://github.com/peterkhayes/rolling-rate-limiter
// Definitions by: Jonas Lochmann <https://github.com/l-jonas>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
export = RollingRateLimiter;
declare function RollingRateLimiter(options: RollingRateLimiter.InMemoryOptions): RollingRateLimiter.SyncOrAsyncLimiter;
declare function RollingRateLimiter(options: RollingRateLimiter.WithRedisOptions): RollingRateLimiter.AsyncLimiter;
declare namespace RollingRateLimiter {
interface GeneralOptions {
interval: number;
maxInInterval: number;
minDifference?: number;
}
interface RedisOptions {
redis: CompatibleRedisClient;
namespace?: string;
}
interface CompatibleRedisClient {
multi: () => any;
}
type InMemoryOptions = GeneralOptions;
type WithRedisOptions = GeneralOptions & RedisOptions;
type AsyncLimiterWithToken = (token: string, callback: AsyncLimiterCallback) => void;
type AsyncLimiterWithoutToken = (callback: AsyncLimiterCallback) => void;
type AsyncLimiterCallback = (err: any, timeLeft: number, actionsLeft: number) => void;
type AsyncLimiter = AsyncLimiterWithToken & AsyncLimiterWithToken;
type SyncLimiter = (token?: string) => number;
type SyncOrAsyncLimiter = SyncLimiter & AsyncLimiter;
}
@@ -0,0 +1,36 @@
import * as RateLimiter from 'rolling-rate-limiter';
/*
Setup:
*/
const limiter = RateLimiter({
// in miliseconds
interval: 1000,
maxInInterval: 10,
// optional: the minimum time (in miliseconds) between any two actions
minDifference: 100
});
/*
Action:
*/
function attemptAction(userId: string) {
// Argument should be a unique identifier for a user if one exists.
// If none is provided, the limiter will not differentiate between users.
const timeLeft = limiter(userId);
if (timeLeft > 0) {
// limit was exceeded, action should not be allowed
// timeLeft is the number of ms until the next action will be allowed
// note that this can be treated as a boolean, since 0 is falsy
} else {
// limit was not exceeded, action should be allowed
}
}
/*
Note that the in-memory version can also operate asynchronously.
The syntax is identical to the redis implementation below.
*/
+23
View File
@@ -0,0 +1,23 @@
{
"compilerOptions": {
"module": "commonjs",
"lib": [
"es6"
],
"noImplicitAny": true,
"noImplicitThis": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"baseUrl": "../",
"typeRoots": [
"../"
],
"types": [],
"noEmit": true,
"forceConsistentCasingInFileNames": true
},
"files": [
"index.d.ts",
"rolling-rate-limiter-tests.ts"
]
}
+1
View File
@@ -0,0 +1 @@
{ "extends": "dtslint/dt.json" }