Skip to content

refactor(rate-limit): use mutex-protected state for fixed-window limiter#2525

Merged
tusharmath merged 2 commits intomainfrom
fix-race-cond
Mar 11, 2026
Merged

refactor(rate-limit): use mutex-protected state for fixed-window limiter#2525
tusharmath merged 2 commits intomainfrom
fix-race-cond

Conversation

@tusharmath
Copy link
Copy Markdown
Collaborator

@tusharmath tusharmath commented Mar 11, 2026

Summary

Refactor the tracker rate limiter to use a single mutex-protected state instead of separate atomics, ensuring consistent fixed-window behavior under concurrent access.

Context

The previous implementation maintained window_start and count as separate atomics and coordinated resets with compare-and-swap logic. While lock-free, this split-state approach can be harder to reason about for fixed-window correctness and race behavior when many threads check/reset simultaneously.

Changes

  • Replaced AtomicU64 + AtomicUsize fields with a Mutex<State> containing both window_start and count.
  • Added a private check_at(now: u64) helper to centralize window logic and enable deterministic testing.
  • Updated check() to delegate to check_at(Utc::now().timestamp() as u64).
  • Improved API docs for RateLimiter::new and RateLimiter::check.
  • Reworked tests to assert full expected sequences for:
    • blocking once the per-minute limit is reached
    • resetting behavior after a new window begins

Key Implementation Details

The limiter now acquires a single mutex lock for each check, then performs window rollover and counter increment atomically within that critical section:

  1. Reset state when now - window_start >= 60.
  2. Reject when count >= max_per_minute.
  3. Otherwise increment and allow.

This keeps all mutable limiter state transitions in one place and avoids interleaving across independent atomic variables.

Use Cases

  • High-frequency event tracking where multiple threads may call check() at the same time.
  • Stable fixed-window throttling semantics for analytics/event dispatch.
  • Easier maintenance and extension of limiter logic due to consolidated state handling.

Testing

cargo test -p forge_tracker rate_limit

Expected result:

  • test_rate_limiter_blocks_after_limit passes
  • test_rate_limiter_resets_on_new_window passes

Links

  • Related issues: N/A
  • Target module: crates/forge_tracker/src/rate_limit.rs

@github-actions github-actions Bot added the type: refactor Code refactoring and restructuring. label Mar 11, 2026
@tusharmath tusharmath changed the title refactor(rate-limit): use mutex instead of atomics refactor(rate-limit): use mutex-protected state for fixed-window limiter Mar 11, 2026
@tusharmath tusharmath merged commit 6884ef5 into main Mar 11, 2026
10 checks passed
@tusharmath tusharmath deleted the fix-race-cond branch March 11, 2026 11:14
tusharmath added a commit that referenced this pull request Mar 13, 2026
…ter (#2525)

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type: refactor Code refactoring and restructuring.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant