2024-04-15 17:01:47 -04:00
|
|
|
import { RateLimiterRedis } from "rate-limiter-flexible";
|
|
|
|
import * as redis from "redis";
|
2024-04-20 14:02:22 -07:00
|
|
|
import { RateLimiterMode } from "../../src/types";
|
2024-04-15 17:01:47 -04:00
|
|
|
|
2024-05-19 12:59:29 -07:00
|
|
|
const MAX_CRAWLS_PER_MINUTE_STARTER = 3;
|
|
|
|
const MAX_CRAWLS_PER_MINUTE_STANDARD = 5;
|
2024-04-15 17:01:47 -04:00
|
|
|
const MAX_CRAWLS_PER_MINUTE_SCALE = 20;
|
|
|
|
|
2024-05-19 12:59:29 -07:00
|
|
|
const MAX_SCRAPES_PER_MINUTE_STARTER = 20;
|
2024-05-19 13:05:36 -07:00
|
|
|
const MAX_SCRAPES_PER_MINUTE_STANDARD = 40;
|
2024-05-19 12:59:29 -07:00
|
|
|
const MAX_SCRAPES_PER_MINUTE_SCALE = 50;
|
2024-04-15 17:01:47 -04:00
|
|
|
|
2024-05-19 12:59:29 -07:00
|
|
|
const MAX_SEARCHES_PER_MINUTE_STARTER = 20;
|
2024-05-19 13:05:36 -07:00
|
|
|
const MAX_SEARCHES_PER_MINUTE_STANDARD = 40;
|
2024-05-19 12:59:29 -07:00
|
|
|
const MAX_SEARCHES_PER_MINUTE_SCALE = 50;
|
2024-05-19 12:45:46 -07:00
|
|
|
|
2024-05-14 18:08:31 -03:00
|
|
|
const MAX_REQUESTS_PER_MINUTE_PREVIEW = 5;
|
|
|
|
const MAX_REQUESTS_PER_MINUTE_ACCOUNT = 20;
|
2024-05-19 12:59:29 -07:00
|
|
|
const MAX_REQUESTS_PER_MINUTE_CRAWL_STATUS = 150;
|
2024-04-20 14:02:22 -07:00
|
|
|
|
2024-04-15 17:01:47 -04:00
|
|
|
export const redisClient = redis.createClient({
|
|
|
|
url: process.env.REDIS_URL,
|
|
|
|
legacyMode: true,
|
|
|
|
});
|
|
|
|
|
|
|
|
export const previewRateLimiter = new RateLimiterRedis({
|
|
|
|
storeClient: redisClient,
|
2024-05-14 14:26:42 -07:00
|
|
|
keyPrefix: "preview",
|
2024-04-15 17:01:47 -04:00
|
|
|
points: MAX_REQUESTS_PER_MINUTE_PREVIEW,
|
|
|
|
duration: 60, // Duration in seconds
|
|
|
|
});
|
|
|
|
|
|
|
|
export const serverRateLimiter = new RateLimiterRedis({
|
|
|
|
storeClient: redisClient,
|
2024-05-14 14:26:42 -07:00
|
|
|
keyPrefix: "server",
|
2024-04-15 17:01:47 -04:00
|
|
|
points: MAX_REQUESTS_PER_MINUTE_ACCOUNT,
|
|
|
|
duration: 60, // Duration in seconds
|
|
|
|
});
|
|
|
|
|
2024-04-20 14:02:22 -07:00
|
|
|
export const crawlStatusRateLimiter = new RateLimiterRedis({
|
|
|
|
storeClient: redisClient,
|
2024-05-14 14:26:42 -07:00
|
|
|
keyPrefix: "crawl-status",
|
2024-04-20 14:02:22 -07:00
|
|
|
points: MAX_REQUESTS_PER_MINUTE_CRAWL_STATUS,
|
|
|
|
duration: 60, // Duration in seconds
|
|
|
|
});
|
|
|
|
|
2024-05-08 15:14:39 -07:00
|
|
|
export const testSuiteRateLimiter = new RateLimiterRedis({
|
|
|
|
storeClient: redisClient,
|
2024-05-14 14:26:42 -07:00
|
|
|
keyPrefix: "test-suite",
|
2024-05-19 12:23:34 -07:00
|
|
|
points: 10000,
|
2024-05-08 15:14:39 -07:00
|
|
|
duration: 60, // Duration in seconds
|
|
|
|
});
|
|
|
|
|
2024-04-15 17:01:47 -04:00
|
|
|
|
2024-05-19 12:45:46 -07:00
|
|
|
export function getRateLimiter(mode: RateLimiterMode, token: string, plan?: string){
|
2024-05-08 12:18:53 -07:00
|
|
|
// Special test suite case. TODO: Change this later.
|
2024-05-21 18:53:58 -07:00
|
|
|
if (token.includes("5089cefa58") || token.includes("6254cf9")){
|
2024-05-08 15:14:39 -07:00
|
|
|
return testSuiteRateLimiter;
|
2024-05-08 12:18:53 -07:00
|
|
|
}
|
2024-05-14 18:08:31 -03:00
|
|
|
switch (mode) {
|
2024-04-20 14:10:29 -07:00
|
|
|
case RateLimiterMode.Preview:
|
|
|
|
return previewRateLimiter;
|
|
|
|
case RateLimiterMode.CrawlStatus:
|
|
|
|
return crawlStatusRateLimiter;
|
2024-05-19 12:45:46 -07:00
|
|
|
case RateLimiterMode.Crawl:
|
|
|
|
if (plan === "standard"){
|
|
|
|
return new RateLimiterRedis({
|
|
|
|
storeClient: redisClient,
|
|
|
|
keyPrefix: "crawl-standard",
|
|
|
|
points: MAX_CRAWLS_PER_MINUTE_STANDARD,
|
|
|
|
duration: 60, // Duration in seconds
|
|
|
|
});
|
|
|
|
} else if (plan === "scale"){
|
|
|
|
return new RateLimiterRedis({
|
|
|
|
storeClient: redisClient,
|
|
|
|
keyPrefix: "crawl-scale",
|
|
|
|
points: MAX_CRAWLS_PER_MINUTE_SCALE,
|
|
|
|
duration: 60, // Duration in seconds
|
|
|
|
});
|
|
|
|
}
|
|
|
|
return new RateLimiterRedis({
|
|
|
|
storeClient: redisClient,
|
|
|
|
keyPrefix: "crawl-starter",
|
|
|
|
points: MAX_CRAWLS_PER_MINUTE_STARTER,
|
|
|
|
duration: 60, // Duration in seconds
|
|
|
|
});
|
|
|
|
case RateLimiterMode.Scrape:
|
|
|
|
if (plan === "standard"){
|
|
|
|
return new RateLimiterRedis({
|
|
|
|
storeClient: redisClient,
|
|
|
|
keyPrefix: "scrape-standard",
|
|
|
|
points: MAX_SCRAPES_PER_MINUTE_STANDARD,
|
|
|
|
duration: 60, // Duration in seconds
|
|
|
|
});
|
|
|
|
} else if (plan === "scale"){
|
|
|
|
return new RateLimiterRedis({
|
|
|
|
storeClient: redisClient,
|
|
|
|
keyPrefix: "scrape-scale",
|
|
|
|
points: MAX_SCRAPES_PER_MINUTE_SCALE,
|
|
|
|
duration: 60, // Duration in seconds
|
|
|
|
});
|
|
|
|
}
|
|
|
|
return new RateLimiterRedis({
|
|
|
|
storeClient: redisClient,
|
|
|
|
keyPrefix: "scrape-starter",
|
|
|
|
points: MAX_SCRAPES_PER_MINUTE_STARTER,
|
|
|
|
duration: 60, // Duration in seconds
|
|
|
|
});
|
|
|
|
case RateLimiterMode.Search:
|
|
|
|
if (plan === "standard"){
|
|
|
|
return new RateLimiterRedis({
|
|
|
|
storeClient: redisClient,
|
|
|
|
keyPrefix: "search-standard",
|
|
|
|
points: MAX_SEARCHES_PER_MINUTE_STANDARD,
|
|
|
|
duration: 60, // Duration in seconds
|
|
|
|
});
|
|
|
|
} else if (plan === "scale"){
|
|
|
|
return new RateLimiterRedis({
|
|
|
|
storeClient: redisClient,
|
|
|
|
keyPrefix: "search-scale",
|
|
|
|
points: MAX_SEARCHES_PER_MINUTE_SCALE,
|
|
|
|
duration: 60, // Duration in seconds
|
|
|
|
});
|
|
|
|
}
|
|
|
|
return new RateLimiterRedis({
|
|
|
|
storeClient: redisClient,
|
|
|
|
keyPrefix: "search-starter",
|
|
|
|
points: MAX_SEARCHES_PER_MINUTE_STARTER,
|
|
|
|
duration: 60, // Duration in seconds
|
|
|
|
});
|
2024-04-20 14:10:29 -07:00
|
|
|
default:
|
|
|
|
return serverRateLimiter;
|
2024-04-15 17:01:47 -04:00
|
|
|
}
|
|
|
|
}
|