Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add missing get/set types, improve documentation #110

Merged
merged 2 commits into from
May 4, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
288 changes: 242 additions & 46 deletions lib/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ export interface IRateLimiterRes {
}

export class RateLimiterRes {
constructor(remainingPoints?: number, msBeforeNext?: number, consumedPoints?: number, isFirstInDuration?: boolean);
constructor(
remainingPoints?: number,
msBeforeNext?: number,
consumedPoints?: number,
isFirstInDuration?: boolean
);

readonly msBeforeNext: number;
readonly remainingPoints: number;
Expand All @@ -25,21 +30,177 @@ export class RateLimiterRes {
export class RateLimiterAbstract {
constructor(opts: IRateLimiterOptions);

consume(key: string | number, pointsToConsume?: number, options?: {[key: string]: any }): Promise<RateLimiterRes>;

penalty(key: string | number, points?: number, options?: {[key: string]: any }): Promise<RateLimiterRes>;

reward(key: string | number, points?: number, options?: {[key: string]: any }): Promise<RateLimiterRes>;

block(key: string | number, secDuration: number, options?: {[key: string]: any }): Promise<RateLimiterRes>;

get(key: string | number, options?: {[key: string]: any }): Promise<RateLimiterRes|null>;

set(key: string | number, points: number, secDuration: number, options?: {[key: string]: any }): Promise<RateLimiterRes>;

delete(key: string | number, options?: {[key: string]: any }): Promise<boolean>;

/**
* Maximum number of points can be consumed over duration. Limiter compares this number with
* number of consumed points by key to decide if an operation should be rejected or resolved.
*/
points: number;

/**
* Number of seconds before consumed points are reset.
* Keys never expire, if duration is 0.
*/
duration: number;

/**
* duration in milliseconds
*/
get msDuration(): number;

/**
* If positive number and consumed more than points in current duration, block for blockDuration
* seconds.
*/
blockDuration: number;

/**
* blockDuration in milliseconds
*/
get msBlockDuration(): number;

/**
* Delay action to be executed evenly over duration First action in duration is executed without
* delay. All next allowed actions in current duration are delayed by formula
* msBeforeDurationEnd / (remainingPoints + 2) with minimum delay of duration * 1000 / points.
* It allows to cut off load peaks similar way to Leaky Bucket.
*
* Note: it isn't recommended to use it for long duration and few points, as it may delay action
* for too long with default execEvenlyMinDelayMs.
*/
execEvenly: boolean;

/**
* Sets minimum delay in milliseconds, when action is delayed with execEvenly
*/
execEvenlyMinDelayMs: number;

/**
* If you need to create several limiters for different purpose.
* Set to empty string '', if keys should be stored without prefix.
*/
keyPrefix: string;

/**
* Returns internal key prefixed with keyPrefix option as it is saved in store.
*/
getKey(key: string | number): string;

/**
* Returns internal key without the keyPrefix.
*/
parseKey(rlKey: string): string;

/**
* @param key is usually IP address or some unique client id
* @param pointsToConsume number of points consumed. default: 1
* @param options is object with additional settings:
* - customDuration expire in seconds for this operation only overwrites limiter's duration. It doesn't work, if key already created.
* @returns Returns Promise, which:
* - `resolved` with `RateLimiterRes` when point(s) is consumed, so action can be done
* - `rejected` only for store and database limiters if insuranceLimiter isn't setup: when some error happened, where reject reason `rejRes` is Error object
* - `rejected` only for RateLimiterCluster if insuranceLimiter isn't setup: when timeoutMs exceeded, where reject reason `rejRes` is Error object
* - `rejected` when there is no points to be consumed, where reject reason `rejRes` is `RateLimiterRes` object
* - `rejected` when key is blocked (if block strategy is set up), where reject reason `rejRes` is `RateLimiterRes` object
*/
consume(
key: string | number,
pointsToConsume?: number,
options?: { [key: string]: any }
): Promise<RateLimiterRes>;

/**
* Fine key by points number of points for one duration.
*
* Note: Depending on time penalty may go to next durations
*
* @returns Returns Promise, which:
* - `resolved` with RateLimiterRes
* - `rejected` only for database limiters if insuranceLimiter isn't setup: when some error happened, where reject reason `rejRes` is Error object
* - `rejected` only for RateLimiterCluster if insuranceLimiter isn't setup: when timeoutMs exceeded, where reject reason `rejRes` is Error object
*/
penalty(
key: string | number,
points?: number,
options?: { [key: string]: any }
): Promise<RateLimiterRes>;

/**
* Reward key by points number of points for one duration.
* Note: Depending on time reward may go to next durations
* @returns Promise, which:
* - `resolved` with RateLimiterRes
* - `rejected` only for database limiters if insuranceLimiter isn't setup: when some error happened, where reject reason `rejRes` is Error object
* - `rejected` only for RateLimiterCluster if insuranceLimiter isn't setup: when timeoutMs exceeded, where reject reason `rejRes` is Error object
*/
reward(
key: string | number,
points?: number,
options?: { [key: string]: any }
): Promise<RateLimiterRes>;

/**
* Get RateLimiterRes in current duration. It always returns RateLimiterRes.isFirstInDuration=false.
* @param key is usually IP address or some unique client id
* @returns Promise, which:
* - `resolved` with RateLimiterRes if key is set
* - `resolved` with null if key is NOT set or expired
* - `rejected` only for database limiters if insuranceLimiter isn't setup: when some error happened, where reject reason `rejRes` is Error object
* - `rejected` only for RateLimiterCluster if insuranceLimiter isn't setup: when timeoutMs exceeded, where reject reason `rejRes` is Error object
*/
get(
key: string | number,
options?: { [key: string]: any }
): Promise<RateLimiterRes | null>;

/**
* Set points to key for secDuration seconds.
* Store it forever, if secDuration is 0.
* @param key
* @param points
* @param secDuration
* @param options
* @returns Promise, which:
* - `resolved` with RateLimiterRes
* - `rejected` only for database limiters if insuranceLimiter isn't setup: when some error happened, where reject reason `rejRes` is Error object
* - `rejected` only for RateLimiterCluster if insuranceLimiter isn't setup: when timeoutMs exceeded, where reject reason `rejRes` is Error object
*/
set(
key: string | number,
points: number,
secDuration: number,
options?: { [key: string]: any }
): Promise<RateLimiterRes>;

/**
* Block key by setting consumed points to points + 1 for secDuration seconds.
*
* It force updates expire, if there is already key.
*
* Blocked key never expires, if secDuration is 0.
* @returns Promise, which:
* - `resolved` with RateLimiterRes
* - `rejected` only for database limiters if insuranceLimiter isn't setup: when some error happened, where reject reason `rejRes` is Error object
* - `rejected` only for RateLimiterCluster if insuranceLimiter isn't setup: when timeoutMs exceeded, where reject reason `rejRes` is Error object
*/
block(
key: string | number,
secDuration: number,
options?: { [key: string]: any }
): Promise<RateLimiterRes>;

/**
* Delete all data related to key.
*
* For example, previously blocked key is not blocked after delete as there is no data anymore.
* @returns Promise, which:
* - `resolved` with boolean, true if data is removed by key, false if there is no such key.
* - `rejected` only for database limiters if insuranceLimiter isn't setup: when some error happened, where reject reason `rejRes` is Error object
* - `rejected` only for RateLimiterCluster if insuranceLimiter isn't setup: when timeoutMs exceeded, where reject reason `rejRes` is Error object
*/
delete(
key: string | number,
options?: { [key: string]: any }
): Promise<boolean>;
}

export class RateLimiterStoreAbstract extends RateLimiterAbstract {
Expand All @@ -55,11 +216,11 @@ interface IRateLimiterOptions {
blockDuration?: number;
}

interface IRateLimiterClusterOptions extends IRateLimiterOptions{
interface IRateLimiterClusterOptions extends IRateLimiterOptions {
timeoutMs?: number;
}

interface IRateLimiterStoreOptions extends IRateLimiterOptions{
interface IRateLimiterStoreOptions extends IRateLimiterOptions {
storeClient: any;
storeType?: string;
inmemoryBlockOnConsumed?: number;
Expand All @@ -70,9 +231,9 @@ interface IRateLimiterStoreOptions extends IRateLimiterOptions{
tableCreated?: boolean;
}

interface IRateLimiterMongoOptions extends IRateLimiterStoreOptions{
interface IRateLimiterMongoOptions extends IRateLimiterStoreOptions {
indexKeyPrefix?: {
[key: string]: any
[key: string]: any;
};
}

Expand All @@ -82,7 +243,7 @@ interface ICallbackReady {

interface IRLWrapperBlackAndWhiteOptions {
limiter: RateLimiterAbstract;
blackList?: string [] | number[];
blackList?: string[] | number[];
whiteList?: string[] | number[];
isBlackListed?(key: any): boolean;
isWhiteListed?(key: any): boolean;
Expand All @@ -105,31 +266,57 @@ export class RateLimiterClusterMasterPM2 {
constructor(pm2: any);
}

export class RateLimiterRedis extends RateLimiterStoreAbstract {
}
export class RateLimiterRedis extends RateLimiterStoreAbstract {}

export interface IRateLimiterMongoFunctionOptions {
attrs: {[key: string]: any};
attrs: { [key: string]: any };
}

export class RateLimiterMongo extends RateLimiterStoreAbstract {
constructor(opts: IRateLimiterMongoOptions);
indexKeyPrefix():Object;
indexKeyPrefix(obj?: Object):void;

consume(key: string | number, pointsToConsume?: number, options?: IRateLimiterMongoFunctionOptions): Promise<RateLimiterRes>;

penalty(key: string | number, points?: number, options?: IRateLimiterMongoFunctionOptions): Promise<RateLimiterRes>;

reward(key: string | number, points?: number, options?: IRateLimiterMongoFunctionOptions): Promise<RateLimiterRes>;

block(key: string | number, secDuration: number, options?: IRateLimiterMongoFunctionOptions): Promise<RateLimiterRes>;

get(key: string | number, options?: IRateLimiterMongoFunctionOptions): Promise<RateLimiterRes|null>;

set(key: string | number, points: number, secDuration: number, options?: IRateLimiterMongoFunctionOptions): Promise<RateLimiterRes>;

delete(key: string | number, options?: IRateLimiterMongoFunctionOptions): Promise<boolean>;
indexKeyPrefix(): Object;
indexKeyPrefix(obj?: Object): void;

consume(
key: string | number,
pointsToConsume?: number,
options?: IRateLimiterMongoFunctionOptions
): Promise<RateLimiterRes>;

penalty(
key: string | number,
points?: number,
options?: IRateLimiterMongoFunctionOptions
): Promise<RateLimiterRes>;

reward(
key: string | number,
points?: number,
options?: IRateLimiterMongoFunctionOptions
): Promise<RateLimiterRes>;

block(
key: string | number,
secDuration: number,
options?: IRateLimiterMongoFunctionOptions
): Promise<RateLimiterRes>;

get(
key: string | number,
options?: IRateLimiterMongoFunctionOptions
): Promise<RateLimiterRes | null>;

set(
key: string | number,
points: number,
secDuration: number,
options?: IRateLimiterMongoFunctionOptions
): Promise<RateLimiterRes>;

delete(
key: string | number,
options?: IRateLimiterMongoFunctionOptions
): Promise<boolean>;
}

export class RateLimiterMySQL extends RateLimiterStoreAbstract {
Expand All @@ -140,8 +327,7 @@ export class RateLimiterPostgres extends RateLimiterStoreAbstract {
constructor(opts: IRateLimiterStoreOptions, cb?: ICallbackReady);
}

export class RateLimiterMemcache extends RateLimiterStoreAbstract {
}
export class RateLimiterMemcache extends RateLimiterStoreAbstract {}

export class RateLimiterUnion {
constructor(...limiters: RateLimiterAbstract[]);
Expand All @@ -154,19 +340,29 @@ export class RLWrapperBlackAndWhite extends RateLimiterAbstract {
}

interface IRateLimiterQueueOpts {
maxQueueSize?: number,
maxQueueSize?: number;
}

export class RateLimiterQueue {
constructor(limiterFlexible: RateLimiterAbstract | BurstyRateLimiter, opts?: IRateLimiterQueueOpts);
constructor(
limiterFlexible: RateLimiterAbstract | BurstyRateLimiter,
opts?: IRateLimiterQueueOpts
);

getTokensRemaining(key?: string | number): Promise<number>;

removeTokens(tokens: number, key?: string | number): Promise<number>;
}

export class BurstyRateLimiter {
constructor(rateLimiter: RateLimiterAbstract, burstLimiter: RateLimiterAbstract)

consume(key: string | number, pointsToConsume?: number, options?: IRateLimiterMongoFunctionOptions): Promise<RateLimiterRes>;
constructor(
rateLimiter: RateLimiterAbstract,
burstLimiter: RateLimiterAbstract
);

consume(
key: string | number,
pointsToConsume?: number,
options?: IRateLimiterMongoFunctionOptions
): Promise<RateLimiterRes>;
}