From 312f27146187728d1dedbd521a852e097099c7d6 Mon Sep 17 00:00:00 2001 From: Pratik Agarwal Date: Thu, 2 Nov 2023 15:32:14 -0300 Subject: [PATCH] chore: refining README for rate-limter as per comments --- examples/nodejs/rate-limiter/README.md | 15 +++++++++++---- .../nodejs/rate-limiter/momento-rate-limiter.ts | 14 ++++++-------- examples/nodejs/rate-limiter/rate-limiter.ts | 1 - examples/nodejs/rate-limiter/worker.ts | 16 +++++++++------- 4 files changed, 26 insertions(+), 20 deletions(-) diff --git a/examples/nodejs/rate-limiter/README.md b/examples/nodejs/rate-limiter/README.md index 7692a8c20..b2e341f22 100644 --- a/examples/nodejs/rate-limiter/README.md +++ b/examples/nodejs/rate-limiter/README.md @@ -25,7 +25,7 @@ Incorporating the `MomentoRateLimiter` class into your application is a straight To get started with the rate-limiter: - You will need a Momento API key. You can obtain one from the [Momento Console](https://console.gomomento.com). -- You will need to create a cache called `rate-limiter` from the console as well! +- You will need to create a cache called `rate-limiter` from the console as well! You can choose a different cache name and pass it to the rate-limiter constructor if you'd like. Once you have the key and the cache created, you can begin integration! Remember to store your API key in an environment variable named `MOMENTO_API_KEY`. @@ -39,7 +39,8 @@ const momento = await CacheClient.create({ }); const tpmLimit = 10; -const rateLimiter = new MomentoRateLimiter(momento, tpmLimit); +const cacheName = "rate-limier"; +const rateLimiter = new MomentoRateLimiter(momento, tpmLimit, cacheName); // test rate limiter const limitExceeded : boolean = await rateLimiter.isLimitExceeded(`id`); @@ -88,7 +89,7 @@ All tasks complete! ``` -There are three additional arguments that you can provide to the rate-limiter if you want to experiment with different configurations: +There are three additional arguments that you can provide to the simulator if you want to experiment with the rate-limiter: - totalRequests: The total number of requests that the example will simulate, defaulted to 1000. - randomDelayUpperBound: The simulation adds a random delay between 0 and the randomDelayUpperBound, defaulted to 60 seconds. @@ -97,7 +98,13 @@ There are three additional arguments that you can provide to the rate-limiter if To override totalRequests to 10, randomDelayUpperBound to 60, and tpmLimit to 1, the command will look like: ```bash -MOMENTO_API_KEY="yourApiKey" npm run rate-limiter 10 60 1 +MOMENTO_API_KEY="yourApiKey" npm run rate-limiter -- 10 60 1 +``` + +The displayed output above indicates a 100% success rate. To observe throttles, modify the configuration as below, which results in approximately half of the requests being throttled. The rate limit is set to 10 requests per user, and we distribute 20 requests among 5 users (totaling 100 requests), introducing a random delay ranging from 0 to 500 milliseconds between each request. + +```bash +MOMENTO_API_KEY="yourApiKey" npm run rate-limiter -- 100 500 10 ``` ## Analysis diff --git a/examples/nodejs/rate-limiter/momento-rate-limiter.ts b/examples/nodejs/rate-limiter/momento-rate-limiter.ts index fe23d84ee..3edee7d7a 100644 --- a/examples/nodejs/rate-limiter/momento-rate-limiter.ts +++ b/examples/nodejs/rate-limiter/momento-rate-limiter.ts @@ -1,25 +1,23 @@ import { CacheClient, CacheIncrement, CacheUpdateTtl } from "@gomomento/sdk"; -import { - AbstractRateLimiter, - RATE_LIMITER_CACHE_NAME, - RATE_LIMITER_TTL_MILLIS, -} from "./rate-limiter"; +import { AbstractRateLimiter, RATE_LIMITER_TTL_MILLIS } from "./rate-limiter"; export class MomentoRateLimiter extends AbstractRateLimiter { _client: CacheClient; _limit: number; + _cacheName: string; - constructor(client: CacheClient, limit: number) { + constructor(client: CacheClient, limit: number, cacheName: string) { super(); this._client = client; this._limit = limit; + this._cacheName = cacheName; } public async isLimitExceeded(id: string): Promise { const currentMinuteKey = this.generateMinuteKey(id); // we do not pass a TTL to this; we don't know if the key for this user was present or not const resp = await this._client.increment( - RATE_LIMITER_CACHE_NAME, + this._cacheName, currentMinuteKey ); @@ -29,7 +27,7 @@ export class MomentoRateLimiter extends AbstractRateLimiter { // we set the TTL for this minute's key to 60 seconds now. if (resp.value() === 1) { const updateTTLResp = await this._client.updateTtl( - RATE_LIMITER_CACHE_NAME, + this._cacheName, currentMinuteKey, RATE_LIMITER_TTL_MILLIS ); diff --git a/examples/nodejs/rate-limiter/rate-limiter.ts b/examples/nodejs/rate-limiter/rate-limiter.ts index 160dea1ed..c556ff762 100644 --- a/examples/nodejs/rate-limiter/rate-limiter.ts +++ b/examples/nodejs/rate-limiter/rate-limiter.ts @@ -4,7 +4,6 @@ export interface RateLimiter { // since our rate limiting buckets are per minute, we expire keys every minute export const RATE_LIMITER_TTL_MILLIS = 60000; -export const RATE_LIMITER_CACHE_NAME = "rate-limiter"; export abstract class AbstractRateLimiter implements RateLimiter { abstract isLimitExceeded(id: string): Promise; diff --git a/examples/nodejs/rate-limiter/worker.ts b/examples/nodejs/rate-limiter/worker.ts index 6f79d5699..336fbd7c3 100644 --- a/examples/nodejs/rate-limiter/worker.ts +++ b/examples/nodejs/rate-limiter/worker.ts @@ -6,7 +6,7 @@ import { } from "@gomomento/sdk"; import { DummyService } from "./service"; import { MomentoRateLimiter } from "./momento-rate-limiter"; -import { RATE_LIMITER_CACHE_NAME, RateLimiter } from "./rate-limiter"; +import { RateLimiter } from "./rate-limiter"; import { Metrics } from "./metrics"; async function main() { @@ -18,11 +18,6 @@ async function main() { defaultTtlSeconds: 6000, }); - const resp = await momento.createCache(RATE_LIMITER_CACHE_NAME); - if (resp instanceof CreateCache.Error) { - throw new Error(`Failed to create cache ${RATE_LIMITER_CACHE_NAME}`); - } - // default values let totalRequests = 1000; let randomDelayUpperBound = 60000; @@ -42,7 +37,14 @@ async function main() { const service = new DummyService(); const rateLimiterMetrics = new Metrics(); - const rateLimiter = new MomentoRateLimiter(momento, tpmLimit); + const cacheName = `rate-limiter`; + + const resp = await momento.createCache(cacheName); + if (resp instanceof CreateCache.Error) { + throw new Error(`Failed to create cache ${cacheName}`); + } + + const rateLimiter = new MomentoRateLimiter(momento, tpmLimit, cacheName); const userIDs = ["user1", "user2", "user3", "user4", "user5"]; const tasks = [];