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

feat: use cloudflare's ratelimiter if possible #2544

Merged
merged 4 commits into from
Oct 23, 2024
Merged

feat: use cloudflare's ratelimiter if possible #2544

merged 4 commits into from
Oct 23, 2024

Conversation

chronark
Copy link
Collaborator

@chronark chronark commented Oct 23, 2024

According to our data, these 5 ratelimit configs cover nearly 75% of our
ratelimit operations.

By using cloudflare for these, I expect our latency to drop and accuracy
to increase

Summary by CodeRabbit

  • New Features

    • Introduced Cloudflare rate limiting functionality, enhancing the app's ability to manage traffic.
    • Expanded environment configurations to include multiple rate limit settings for different thresholds.
  • Bug Fixes

    • Improved error handling in the rate limiting process to provide better logging and metrics.
  • Documentation

    • Updated metric schema to include new options for categorizing rate limiting metrics, allowing for better tracking and analysis.

According to our data, these 5 ratelimit configs cover nearly 75% of our
ratelimit operations.

By using cloudflare for these, I expect our latency to drop and accuracy
to increase
Copy link

vercel bot commented Oct 23, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
engineering ✅ Ready (Inspect) Visit Preview 💬 Add feedback Oct 23, 2024 0:24am
play ✅ Ready (Inspect) Visit Preview 💬 Add feedback Oct 23, 2024 0:24am
www ✅ Ready (Inspect) Visit Preview 💬 Add feedback Oct 23, 2024 0:24am
2 Skipped Deployments
Name Status Preview Comments Updated (UTC)
dashboard ⬜️ Ignored (Inspect) Visit Preview Oct 23, 2024 0:24am
workflows ⬜️ Ignored (Inspect) Visit Preview Oct 23, 2024 0:24am

Copy link

changeset-bot bot commented Oct 23, 2024

⚠️ No Changeset found

Latest commit: 4726897

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Copy link
Contributor

coderabbitai bot commented Oct 23, 2024

📝 Walkthrough
📝 Walkthrough

Walkthrough

This pull request introduces several enhancements related to rate limiting functionality across multiple files. A new constant cloudflareRatelimiter is added to manage rate limits using the Zod library. The AgentRatelimiter class is updated to prioritize the Cloudflare rate limiter, with improved error handling and metrics logging. Additionally, new rate limit bindings are defined in the wrangler.toml file for various environments, and the metric schema is modified to include Cloudflare as a source option.

Changes

File Change Summary
apps/api/src/pkg/env.ts Added cloudflareRatelimiter constant and five new properties (RL_10_60s, RL_30_60s, RL_200_60s, RL_500_10s, RL_200_10s) to zEnv.
apps/api/src/pkg/ratelimit/client.ts Modified AgentRatelimiter class to integrate cloudflareRatelimiter, enhance error handling, and update metrics logging.
apps/api/wrangler.toml Added new rate limit bindings for development, preview, canary, and production environments with specified limits and periods.
internal/metrics/src/index.ts Updated metricSchema to expand source field in metric.ratelimit to include "cloudflare".

Possibly related PRs

  • fix: cf cache ratelimits #2112: This PR addresses issues related to rate limits in the context of caching on Cloudflare, which is directly relevant to the changes made in the main PR that introduces rate limiting configurations using cloudflareRatelimiter.
  • feat: allow-developer-to-set-a-custom-refill-time-when-using-the #2114: This PR introduces a new feature allowing developers to set a custom refill time, which includes modifications to rate limiting configurations in the v1_keys_verifyKey.ts file, aligning with the rate limiting enhancements in the main PR.

Suggested reviewers

  • mcstepp
  • perkinsjr

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

github-actions bot commented Oct 23, 2024

Thank you for following the naming conventions for pull request titles! 🙏

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Outside diff range and nitpick comments (3)
apps/api/wrangler.toml (2)

39-45: Fix typo in comment.

There's a typo in the comment: "nameing" should be "naming"

-# The nameing scheme is important, because we're dynamically constructing
+# The naming scheme is important, because we're dynamically constructing

Line range hint 38-261: Consider environment-specific rate limits.

The rate limit configurations are identical across all environments (development, preview, canary, and production). While this consistency can be beneficial, consider:

  1. Whether production needs different (possibly stricter) limits
  2. Whether canary should match production exactly (as noted in the comment that canary settings should match production)
  3. Whether development/preview environments could benefit from more relaxed limits
apps/api/src/pkg/ratelimit/client.ts (1)

91-93: Include error stack trace in logs for better debugging

When logging the error in the catch block, consider including the stack trace to facilitate easier debugging and troubleshooting.

Apply this diff to enhance error logging:

 this.logger.error("cfrl failed, falling back to agent", {
   error: (err as Error).message,
+  stack: (err as Error).stack,
 });
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between b456ac0 and 0820371.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (4)
  • apps/api/src/pkg/env.ts (2 hunks)
  • apps/api/src/pkg/ratelimit/client.ts (2 hunks)
  • apps/api/wrangler.toml (4 hunks)
  • internal/metrics/src/index.ts (1 hunks)
🧰 Additional context used
🔇 Additional comments (8)
apps/api/src/pkg/env.ts (1)

49-53: Document rate limit configurations and verify bindings.

While the naming is clear, adding documentation for each rate limit configuration would improve maintainability. Also, let's verify these match the wrangler.toml bindings.

Consider adding JSDoc comments:

+  /** Rate limit: 10 requests per 60 seconds */
   RL_10_60s: cloudflareRatelimiter,
+  /** Rate limit: 30 requests per 60 seconds */
   RL_30_60s: cloudflareRatelimiter,
+  /** Rate limit: 200 requests per 60 seconds */
   RL_200_60s: cloudflareRatelimiter,
+  /** Rate limit: 500 requests per 10 seconds */
   RL_500_10s: cloudflareRatelimiter,
+  /** Rate limit: 200 requests per 10 seconds */
   RL_200_10s: cloudflareRatelimiter,

Let's verify the bindings in wrangler.toml:

✅ Verification successful

Rate limit configurations are properly bound in wrangler.toml

The verification shows that all rate limit configurations in env.ts have corresponding bindings in wrangler.toml with correct names and types. Each rate limiter is properly configured as a "ratelimit" type with a unique namespace ID. The original suggestion for adding JSDoc comments still stands as a documentation improvement.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that the rate limit configurations match in wrangler.toml
# Expected: Each rate limit should have corresponding bindings in wrangler.toml

echo "Checking rate limit bindings in wrangler.toml..."
rg "RL_(10|30|200|500)_(10|60)s" -A 2

Length of output: 3246

internal/metrics/src/index.ts (2)

82-82: LGTM: Mode enum updated to support Cloudflare ratelimiter

The addition of "cloudflare" to the mode enum aligns with the PR objective of implementing Cloudflare's ratelimiter for specific configurations.


85-85: LGTM: Source enum updated for Cloudflare integration

The addition of "cloudflare" to the source enum enables proper tracking of metrics from the Cloudflare ratelimiter implementation.

Let's verify the consistency of these enum values across the codebase:

✅ Verification successful

Based on the shell script results, I can now generate the final response as we have sufficient information to verify the consistency of the enum values across the codebase.

Verified: Source and mode enums are consistently used across the codebase

The verification confirms that:

  • The source enum values ("agent", "durable_object", "cloudflare") are consistently defined in internal/metrics/src/index.ts and correctly used in apps/api/src/pkg/ratelimit/client.ts
  • The mode enum values ("sync", "async", "cloudflare") are properly implemented and referenced across the codebase, including:
    • Schema definition in internal/metrics/src/index.ts
    • Implementation in apps/api/src/pkg/ratelimit/client.ts
    • Documentation in apps/docs/ratelimiting/modes.mdx
    • UI components in the dashboard
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of ratelimit modes and sources
# Expected: All references should use consistent enum values

# Check for ratelimit mode usage
echo "Checking ratelimit mode usage..."
rg -A 2 'mode.*sync|mode.*async|mode.*cloudflare'

# Check for ratelimit source usage
echo "Checking ratelimit source usage..."
rg -A 2 'source.*agent|source.*durable_object|source.*cloudflare'

Length of output: 4272

apps/api/wrangler.toml (3)

38-74: Review the rate limit values for development environment.

The rate limit configurations look reasonable, but consider if the development environment should have more lenient limits to facilitate testing and debugging.

Would it make sense to:

  1. Increase limits in development for easier testing?
  2. Add documentation about how these limits were chosen (e.g., based on usage patterns)?

44-45: Consider documenting namespace ID collision prevention.

The namespace ID schema using 9900 prefix is duplicated across all environments. While this might be intentional, it would be helpful to document:

  1. Whether these IDs need to be unique across environments
  2. How namespace ID collisions are prevented
  3. Why the specific prefix 9900 was chosen
#!/bin/bash
# Check if namespace IDs are unique across all environments
echo "Checking for duplicate namespace IDs..."
rg "namespace_id = \"[0-9]+\"" -o | sort | uniq -d

Also applies to: 103-111, 162-170, 224-232


Line range hint 38-261: Verify dynamic construction of rate limit bindings.

The comment mentions that "The naming scheme is important, because we're dynamically constructing these in the api code". Let's verify how these bindings are being used.

✅ Verification successful

Let me try a different search strategy to find how these rate limit bindings are used in the code.


Based on the search results, I can now provide a final response about the rate limit bindings verification:

Rate limit bindings are correctly configured and used in the codebase

The rate limit bindings defined in wrangler.toml follow a specific naming scheme (RL_{LIMIT}_{DURATION}s) that is used dynamically in the API code. The verification shows:

  • The bindings are properly defined in apps/api/src/pkg/env.ts with matching names: RL_10_60s, RL_30_60s, RL_200_60s, RL_500_10s, RL_200_10s
  • The rate limiter client in apps/api/src/pkg/ratelimit/client.ts dynamically constructs the binding key using the same pattern: `RL_${req.limit}_${Math.round(req.interval / 1000)}s`
  • The namespace IDs follow the documented schema with the 9900 prefix followed by limit and duration
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for dynamic construction of rate limit binding names
echo "Searching for rate limit binding usage..."
rg "RL_\d+_\d+s" --type ts -B 2 -A 2

# Search for potential parsing of these bindings
echo "Searching for binding name parsing..."
ast-grep --pattern 'RL_$_$_' --lang ts

Length of output: 626


Script:

#!/bin/bash
# Search for rate limit related code
echo "Searching for rate limit related code..."
rg "ratelimit|rateLimiter" --type ts -B 2 -A 2

# Search for env.bindings usage
echo "Searching for env.bindings usage..."
rg "env\.bindings" --type ts -B 2 -A 2

# Search for specific rate limit binding names
echo "Searching for specific rate limit binding names..."
rg "RL_10_60s|RL_30_60s|RL_200_60s|RL_500_10s|RL_200_10s" --type ts -B 2 -A 2

Length of output: 334069

apps/api/src/pkg/ratelimit/client.ts (2)

3-3: LGTM!

The import of cloudflareRatelimiter is appropriate and correctly references the module from "../env".


69-94: Integration of Cloudflare rate limiter is well-implemented

The try-catch block properly attempts to use the Cloudflare rate limiter when the binding exists and gracefully falls back to the agent rate limiter in case of failure. This implementation enhances reliability by ensuring that rate limiting continues to function even if the Cloudflare rate limiter is unavailable.

apps/api/src/pkg/env.ts Show resolved Hide resolved
apps/api/src/pkg/ratelimit/client.ts Outdated Show resolved Hide resolved
Copy link
Collaborator

@perkinsjr perkinsjr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (1)
apps/api/src/pkg/ratelimit/client.ts (1)

89-89: Consider preserving actual values in the response

The response currently uses -1 as placeholder values for reset, current, and remaining. This might affect monitoring and debugging capabilities. Consider extracting these values from the Cloudflare response if available.

-          return Ok({ pass: res.success, reset: -1, current: -1, remaining: -1, triggered: null });
+          return Ok({
+            pass: res.success,
+            reset: res.reset ?? -1,
+            current: res.current ?? -1,
+            remaining: res.remaining ?? -1,
+            triggered: null
+          });
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 0820371 and 4726897.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (2)
  • apps/api/src/pkg/ratelimit/client.ts (2 hunks)
  • internal/metrics/src/index.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • internal/metrics/src/index.ts
🧰 Additional context used
🔇 Additional comments (2)
apps/api/src/pkg/ratelimit/client.ts (2)

3-5: LGTM: Clean import integration

The new import for cloudflareRatelimiter is properly integrated and aligns with the PR's objective to use Cloudflare's ratelimiter.


69-96: LGTM: Robust Cloudflare integration with fallback

The implementation correctly:

  • Attempts Cloudflare ratelimiter only for async requests
  • Uses a clear naming convention for binding keys
  • Gracefully falls back to the agent on failure
  • Maintains proper metrics tracking

@chronark chronark added this pull request to the merge queue Oct 23, 2024
Merged via the queue into main with commit 10d978b Oct 23, 2024
27 checks passed
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

Successfully merging this pull request may close these issues.

2 participants