Class: TocDoc::RateLimiter::TokenBucket

Inherits:
Object
  • Object
show all
Defined in:
lib/toc_doc/http/rate_limiter/token_bucket.rb

Overview

A thread-safe token-bucket rate limiter using a monotonic clock.

Tokens are refilled at a fixed rate; when the bucket is empty, #acquire sleeps until the next token is available.

Examples:

Allow 5 requests per second

bucket = TocDoc::RateLimiter::TokenBucket.new(rate: 5)
bucket.acquire  # returns immediately while tokens remain

2 requests per 2 seconds

bucket = TocDoc::RateLimiter::TokenBucket.new(rate: 2, interval: 2.0)

Constant Summary collapse

MIN_RATE =
1.0

Instance Method Summary collapse

Constructor Details

#initialize(rate:, interval: 1.0) ⇒ TokenBucket

Returns a new instance of TokenBucket.

Parameters:

  • rate (Numeric)

    maximum burst capacity and refill amount per +interval+; clamped to a minimum of +1+

  • interval (Float) (defaults to: 1.0)

    refill period in seconds (default: 1.0)



22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/toc_doc/http/rate_limiter/token_bucket.rb', line 22

def initialize(rate:, interval: 1.0)
  raw = rate.to_f
  if raw < MIN_RATE
    warn "[TocDoc] rate_limit #{raw} is below minimum; clamped to #{MIN_RATE}."
    raw = MIN_RATE
  end
  @rate     = raw
  @interval = interval.to_f
  @tokens   = @rate
  @last_refill = Process.clock_gettime(Process::CLOCK_MONOTONIC)
  @mutex = Mutex.new
end

Instance Method Details

#acquire

This method returns an undefined value.

Blocks until a token is available, then consumes it.

The mutex is released while sleeping so other threads can proceed concurrently.



41
42
43
44
45
46
47
48
49
50
51
# File 'lib/toc_doc/http/rate_limiter/token_bucket.rb', line 41

def acquire
  @mutex.synchronize do
    refill
    while @tokens < 1
      sleep_time = @interval / @rate
      @mutex.sleep(sleep_time)
      refill
    end
    @tokens -= 1
  end
end