Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is there a way to combine rate limits? #126

Open
david8z opened this issue Oct 18, 2024 · 4 comments
Open

Is there a way to combine rate limits? #126

david8z opened this issue Oct 18, 2024 · 4 comments

Comments

@david8z
Copy link

david8z commented Oct 18, 2024

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.

@david8z
Copy link
Author

david8z commented Oct 18, 2024

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");
};

@fahreddinozcan
Copy link
Contributor

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.

@david8z
Copy link
Author

david8z commented Oct 26, 2024

Hey @fahreddinozcan basically the idea is finding an efficient way of combining two limits.

@AtiqGauri
Copy link

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants