feat(rate-limit/unstable): add rate limiting module#7063
feat(rate-limit/unstable): add rate limiting module#7063tomas-zijdemans wants to merge 18 commits intodenoland:mainfrom
Conversation
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #7063 +/- ##
==========================================
+ Coverage 94.41% 94.45% +0.04%
==========================================
Files 630 641 +11
Lines 50490 51537 +1047
Branches 8949 9086 +137
==========================================
+ Hits 47669 48680 +1011
- Misses 2249 2273 +24
- Partials 572 584 +12 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
bartlomieju
left a comment
There was a problem hiding this comment.
This is a well-architected and thoroughly tested package. The layered design (pure algorithms → keyed wrapper → async queue/timer/disposal → public API) is clean, and the algorithm implementations look mathematically correct. Solid work.
A few things to address before merge:
Blockers:
- CI: PR title validation is failing —
rate-limitneeds to be added to the scopes list in.github/workflows/title.ymlin a preceding PR. - Discussion: Is there a tracking issue or RFC for adding a rate-limiting package to
@std? This is a significant addition (~5100 lines) and new packages typically need community buy-in. mod.ts: Ensure it has the@moduleJSDoc tag per repo conventions.
Design/correctness notes:
peek()in keyed algorithms mutates state:peek()callsops.advance(), which rotates segment counters in sliding-window. This means "peeking" isn't truly read-only — it advances time. This is necessary for correct metadata but should be documented explicitly.- Depends on unstable APIs: Imports
RollingCounterfrom@std/data-structures/unstable-rolling-counterand usesDeque. Fine for v0.1.0 but worth noting as a stability risk. - TokenBucket
result()usesthis.computeRetryAfter()rather than calling the method directly — minor style inconsistency with the other algorithm implementations which inline the computation. - Some JSDoc examples use
limiter[Symbol.dispose]()syntax — consider using theusingstatement for consistency with newer examples elsewhere. - Naming inconsistency:
TokenBucketOptionsusestokenLimit+tokensPerPeriod+replenishmentPeriod, whilecreateRateLimiteruseslimit+window+tokensPerCycle. The different naming across the same domain could be confusing. - Floating-point edge cases: TokenBucket uses fractional tokens internally (
Math.floor(state.tokens)for remaining). No tests specifically exercise floating-point boundary behavior (e.g., tokens at 4.999... after refill).
|
Thank you for the review. I pushed a new commit now:
Let me know if you agree/disagree or have any further feedback |
…7046) Sliding expiration: entries can now stay alive as long as they're being accessed, with an optional hard deadline. Useful for sessions or rate-limit windows.
Rate limiting strategies for controlling how many operations can occur over time.
The primary API is
createRateLimiter, a keyed rate limiter for the common case of "allow key X at most N requests per window." It supports fixed-window, sliding-window, token-bucket, and GCRA algorithms. For single-resource limiting, use the primitives:createTokenBucket,createFixedWindow, andcreateSlidingWindow.Depends on
@std/data-structures:Dequefor async queue management andRollingCounterfor sliding-window segment tracking.