Is there a way to combine rate limits?
Opened this issue · 4 comments
What is the optimal way to combine two rate limits together?
We could define:
export const ratelimit = {
a: new Ratelimit({
redis,
limiter: Ratelimit.fixedWindow(1000, "60 s"),
}),
b: new Ratelimit({
redis,
limiter: Ratelimit.fixedWindow(3, "10 s"),
})
]
And then await both:
await Promise.all(
ratelimit.a.blockUntilReady("a"),
ratelimit.b.blockUntilReady("b")
)
But this doesn't assures that once resolved none are blocked as one could resolve much faster than the other one.
Ended up implementing this but unsure if there is a better way:
export const rateLimit = async (domain: string, maxRetries = 3) => {
for (let i = 0; i < maxRetries; i++) {
try {
const { success, pending, reset } =
await ratelimit.handinger.blockUntilReady("api", 180_000);
const msToReset = Math.max(0, reset - Date.now());
const { success: successDomain, pending: pendingDomain } =
await ratelimit.handingerDomain.blockUntilReady(domain, msToReset);
waitUntil(Promise.all([pending, pendingDomain]));
if (success && successDomain) {
return;
}
throw new Error("Handinger Ratelimit exceeded");
} catch (error) {
if (i === maxRetries - 1) throw error;
console.warn(
`Rate limit retry ${i + 1}/${maxRetries} failed. Retrying...`,
);
await new Promise((resolve) => setTimeout(resolve, 10000));
}
}
throw new Error("Handinger Ratelimit exceeded");
};
Hey @david8z, what is it that you're trying to achieve here? If you could provide more details about the logic/purpose, I could come up with something.
Hey @fahreddinozcan basically the idea is finding an efficient way of combining two limits.
It would be beneficial to implement multiple rate limits. There are various reasons why one might require multiple rate limits, such as:
Scenario where we provide a rate limit for the current month and another rate limit for a per-minute or per-day rate limit for abuse protection. A function that efficiently combines multiple rate limit validation would be helpful.