Class: RCrewAI::RateLimiter

Inherits:
Object
  • Object
show all
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

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

#acquireObject

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_countObject

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