Class: Philiprehberger::Debounce::RateLimiter
- Inherits:
-
Object
- Object
- Philiprehberger::Debounce::RateLimiter
- Defined in:
- lib/philiprehberger/debounce/rate_limiter.rb
Overview
Sliding window rate limiter.
Instance Method Summary collapse
- #call(key = :default) ⇒ Object
-
#initialize(limit:, window:) ⇒ RateLimiter
constructor
A new instance of RateLimiter.
- #reset(key = :default) ⇒ Object
Constructor Details
#initialize(limit:, window:) ⇒ RateLimiter
Returns a new instance of RateLimiter.
7 8 9 10 11 12 13 14 15 |
# File 'lib/philiprehberger/debounce/rate_limiter.rb', line 7 def initialize(limit:, window:) raise ArgumentError, 'Limit must be a positive integer' unless limit.is_a?(Integer) && limit.positive? raise ArgumentError, 'Window must be a positive number' unless window.is_a?(Numeric) && window.positive? @limit = limit @window = window @requests = Hash.new { |h, k| h[k] = [] } @mutex = Mutex.new end |
Instance Method Details
#call(key = :default) ⇒ Object
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
# File 'lib/philiprehberger/debounce/rate_limiter.rb', line 17 def call(key = :default) now = Process.clock_gettime(Process::CLOCK_MONOTONIC) @mutex.synchronize do cleanup!(key, now) remaining = @limit - @requests[key].length if remaining.positive? @requests[key] << now { allowed: true, remaining: remaining - 1, retry_after: 0 } else oldest = @requests[key].first retry_after = oldest + @window - now { allowed: false, remaining: 0, retry_after: [retry_after, 0].max } end end end |
#reset(key = :default) ⇒ Object
35 36 37 38 |
# File 'lib/philiprehberger/debounce/rate_limiter.rb', line 35 def reset(key = :default) @mutex.synchronize { @requests.delete(key) } self end |