rate limiting

This commit is contained in:
Kaushik Narayan R 2025-03-14 17:25:23 -07:00
parent e39d0381c9
commit 852c907d35
4 changed files with 32 additions and 6 deletions

View File

@ -1,3 +1,5 @@
import Bottleneck from "bottleneck";
import { axiosInstance } from "./axios.ts"; import { axiosInstance } from "./axios.ts";
import { import {
@ -50,6 +52,18 @@ type SingleRequestResult<RespDataType> = Promise<{
message: string; message: string;
}>; }>;
const rateLimiter = new Bottleneck({
// slow start
reservoir: 0,
reservoirIncreaseAmount: 2,
reservoirIncreaseInterval: 1000,
// for bursts
reservoirIncreaseMaximum: 30,
minTime: 200,
maxConcurrent: 10,
});
/** /**
* Spotify API (v1) - one-off request handler * Spotify API (v1) - one-off request handler
*/ */
@ -67,9 +81,13 @@ const singleRequest = async <RespDataType>({
try { try {
if (!data || inlineData) { if (!data || inlineData) {
if (data) config.data = data ?? null; if (data) config.data = data ?? null;
resp = await axiosInstance[method](path, config); resp = await rateLimiter.schedule(() =>
axiosInstance[method](path, config)
);
} else { } else {
resp = await axiosInstance[method](path, data, config); resp = await rateLimiter.schedule(() =>
axiosInstance[method](path, data, config)
);
} }
logger.debug(logPrefix + "Successful response received."); logger.debug(logPrefix + "Successful response received.");
return { resp, message: "" }; return { resp, message: "" };

7
package-lock.json generated
View File

@ -10,6 +10,7 @@
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"axios": "^1.8.2", "axios": "^1.8.2",
"bottleneck": "^2.19.5",
"connect-redis": "^8.0.1", "connect-redis": "^8.0.1",
"cookie-parser": "^1.4.7", "cookie-parser": "^1.4.7",
"cors": "^2.8.5", "cors": "^2.8.5",
@ -895,6 +896,12 @@
"npm": "1.2.8000 || >= 1.4.16" "npm": "1.2.8000 || >= 1.4.16"
} }
}, },
"node_modules/bottleneck": {
"version": "2.19.5",
"resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz",
"integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==",
"license": "MIT"
},
"node_modules/brace-expansion": { "node_modules/brace-expansion": {
"version": "1.1.11", "version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",

View File

@ -22,6 +22,7 @@
"homepage": "https://github.com/20kaushik02/spotify-manager#readme", "homepage": "https://github.com/20kaushik02/spotify-manager#readme",
"dependencies": { "dependencies": {
"axios": "^1.8.2", "axios": "^1.8.2",
"bottleneck": "^2.19.5",
"connect-redis": "^8.0.1", "connect-redis": "^8.0.1",
"cookie-parser": "^1.4.7", "cookie-parser": "^1.4.7",
"cors": "^2.8.5", "cors": "^2.8.5",

View File

@ -34,12 +34,12 @@ class myGraph {
getDirectHeads(node: GNode): GNode[] { getDirectHeads(node: GNode): GNode[] {
return this.edges return this.edges
.filter((edge) => edge.to == node) .filter((edge) => edge.to === node)
.map((edge) => edge.from); .map((edge) => edge.from);
} }
getDirectHeadEdges(node: GNode): GEdge[] { getDirectHeadEdges(node: GNode): GEdge[] {
return this.edges.filter((edge) => edge.to == node); return this.edges.filter((edge) => edge.to === node);
} }
/** BFS */ /** BFS */
@ -61,7 +61,7 @@ class myGraph {
getDirectTails(node: GNode): GNode[] { getDirectTails(node: GNode): GNode[] {
return this.edges return this.edges
.filter((edge) => edge.from == node) .filter((edge) => edge.from === node)
.map((edge) => edge.to); .map((edge) => edge.to);
} }
@ -70,7 +70,7 @@ class myGraph {
* @returns {{ from: string, to: string }[]} * @returns {{ from: string, to: string }[]}
*/ */
getDirectTailEdges(node: GNode): GEdge[] { getDirectTailEdges(node: GNode): GEdge[] {
return this.edges.filter((edge) => edge.from == node); return this.edges.filter((edge) => edge.from === node);
} }
/** BFS */ /** BFS */