Skip to content

Instantly share code, notes, and snippets.

@lihaibh
Last active February 24, 2023 13:39
Show Gist options
  • Save lihaibh/f3abbf999ef3433199342c2d4ab0ff9e to your computer and use it in GitHub Desktop.
Save lihaibh/f3abbf999ef3433199342c2d4ab0ff9e to your computer and use it in GitHub Desktop.
Rate limit wrapper - wraps an async function, make sure the calls do not exceed the rate limit
export function withRateLimit<T, E extends (...args: any[]) => Promise<T>>({ fn, limit, every }: {
fn: E,
// maximum amount of executions in specific amount of time
limit: number,
// the amount in milliseconds we are limiting the total amount of executions
every: number
}): E {
let lastExecTime = -1;
let requestCounter = 0;
let triggerFlushTimeout = null;
let todo = [];
/**
* Flush the requests in the todo queue based on the rate limit.
*/
async function flush() {
// Check if it's been more than a minute since the last execution
if (Date.now() - lastExecTime > every) {
requestCounter = 0;
}
// flush more requests from the todo queue
if (requestCounter < limit) {
const nextCalls = todo.splice(0, limit - requestCounter);
if (nextCalls.length > 0) {
requestCounter += nextCalls.length;
lastExecTime = Date.now();
// execute the requests without waiting them
for (const nextCall of nextCalls) {
nextCall();
}
}
}
// if there are still requests in the todo queue, wait for the remaining time and re-flush
if (todo.length > 0 && !triggerFlushTimeout) {
const remainingTime = (every - (Date.now() - lastExecTime)) + 10;
// trigger flush again
triggerFlushTimeout = setTimeout(() => {
clearTimeout(triggerFlushTimeout);
triggerFlushTimeout = null;
flush();
}, remainingTime);
}
}
return (async (...args: any[]) => {
// await until the function executes by the flush mechanism
const promise = new Promise<T>((resolve, reject) => {
// this the todo requests, will be executed lazily later
todo.push(async () => {
return fn(...args).then(resolve).catch(reject);
});
});
flush();
return promise;
}) as E;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment