Class: RCrewAI::RateLimiter
- Inherits:
-
Object
- Object
- RCrewAI::RateLimiter
- Defined in:
- lib/rcrewai/rate_limiter.rb
Overview
Thread-safe requests-per-minute throttle. Records call timestamps in a
rolling 60-second window; acquire blocks (sleeps) until a slot is free.
The clock and sleeper are injectable so tests can drive time deterministically
without touching the wall clock. max_rpm of nil or 0 means unlimited.
Defined Under Namespace
Classes: ThrottledClient
Constant Summary collapse
- WINDOW =
60.0
Instance Method Summary collapse
-
#acquire ⇒ Object
Blocks until making a call would keep us within max_rpm, then records it.
-
#initialize(max_rpm:, clock: nil, sleeper: nil) ⇒ RateLimiter
constructor
A new instance of RateLimiter.
-
#recent_count ⇒ Object
Number of calls currently inside the window (useful for tests/metrics).
Constructor Details
#initialize(max_rpm:, clock: nil, sleeper: nil) ⇒ RateLimiter
Returns a new instance of RateLimiter.
12 13 14 15 16 17 18 |
# File 'lib/rcrewai/rate_limiter.rb', line 12 def initialize(max_rpm:, clock: nil, sleeper: nil) @max_rpm = max_rpm @clock = clock || -> { current_time } @sleeper = sleeper || ->(seconds) { sleep(seconds) } @calls = [] @mutex = Mutex.new end |
Instance Method Details
#acquire ⇒ Object
Blocks until making a call would keep us within max_rpm, then records it.
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/rcrewai/rate_limiter.rb', line 21 def acquire return record_unlimited if unlimited? loop do wait = @mutex.synchronize do prune(@clock.call) if @calls.length < @max_rpm @calls << @clock.call return end # Time until the oldest in-window call ages out. (@calls.first + WINDOW) - @clock.call end @sleeper.call(wait) if wait.positive? end end |
#recent_count ⇒ Object
Number of calls currently inside the window (useful for tests/metrics).
40 41 42 43 44 45 |
# File 'lib/rcrewai/rate_limiter.rb', line 40 def recent_count @mutex.synchronize do prune(@clock.call) @calls.length end end |