Class: Wikiwiki::RateLimiter
- Inherits:
-
Object
- Object
- Wikiwiki::RateLimiter
- Defined in:
- lib/wikiwiki/rate_limiter.rb
Overview
Rate limiter with pluggable strategies
Constant Summary collapse
- WIKIWIKI_API_LIMITS =
Default rate limits for Wikiwiki REST API
[ {window: 60, max_requests: 120}, # 120 requests per minute {window: 3600, max_requests: 2000} # 2000 requests per hour ].freeze
Instance Attribute Summary collapse
-
#mutex ⇒ Object
readonly
Returns the value of attribute mutex.
Class Method Summary collapse
-
.default ⇒ RateLimiter
Create a rate limiter with default limits (120 requests/min, 2000 requests/hour).
-
.no_limit ⇒ RateLimiter
Create a null rate limiter that never limits.
-
.raise_on_limit(limits) ⇒ RateLimiter
Create a rate limiter that raises error when limit is exceeded.
-
.wait_on_limit(limits) ⇒ RateLimiter
Create a rate limiter that waits when limit is exceeded.
Instance Method Summary collapse
-
#acquire! ⇒ void
Acquire permission to make a request.
-
#can_request? ⇒ Boolean
Check if a request can be made without exceeding any limits.
-
#initialize(limits, strategy) ⇒ RateLimiter
constructor
A new instance of RateLimiter.
-
#record! ⇒ void
Record a new request across all window limiters.
-
#wait_time ⇒ Float?
Get maximum wait time across all window limiters.
-
#wait_time_until_available ⇒ Float
Get time in seconds until next request can be made.
Constructor Details
#initialize(limits, strategy) ⇒ RateLimiter
Returns a new instance of RateLimiter.
72 73 74 75 76 |
# File 'lib/wikiwiki/rate_limiter.rb', line 72 def initialize(limits, strategy) @windows = limits.map {|limit| SlidingWindow.new(**limit) } @mutex = Mutex.new @strategy = strategy end |
Instance Attribute Details
#mutex ⇒ Object (readonly)
Returns the value of attribute mutex.
113 114 115 |
# File 'lib/wikiwiki/rate_limiter.rb', line 113 def mutex @mutex end |
Class Method Details
.default ⇒ RateLimiter
Create a rate limiter with default limits (120 requests/min, 2000 requests/hour)
These are the rate limits for the Wikiwiki REST API.
66 |
# File 'lib/wikiwiki/rate_limiter.rb', line 66 def self.default = wait_on_limit(WIKIWIKI_API_LIMITS) |
.no_limit ⇒ RateLimiter
Create a null rate limiter that never limits
59 |
# File 'lib/wikiwiki/rate_limiter.rb', line 59 def self.no_limit = new([], Strategy::Null.new) |
.raise_on_limit(limits) ⇒ RateLimiter
Create a rate limiter that raises error when limit is exceeded
37 38 39 40 41 |
# File 'lib/wikiwiki/rate_limiter.rb', line 37 def self.raise_on_limit(limits) raise ArgumentError, "limits cannot be empty (use .no_limit for no rate limiting)" if limits.empty? new(limits, Strategy::Raise.new) end |
.wait_on_limit(limits) ⇒ RateLimiter
Create a rate limiter that waits when limit is exceeded
50 51 52 53 54 |
# File 'lib/wikiwiki/rate_limiter.rb', line 50 def self.wait_on_limit(limits) raise ArgumentError, "limits cannot be empty (use .no_limit for no rate limiting)" if limits.empty? new(limits, Strategy::Wait.new) end |
Instance Method Details
#acquire! ⇒ void
This method returns an undefined value.
Acquire permission to make a request
Behavior depends on the strategy:
-
raise_on_limit: raises RateLimitError if limit exceeded
-
wait_on_limit: waits until request can be made
-
no_limit: always succeeds immediately
87 |
# File 'lib/wikiwiki/rate_limiter.rb', line 87 def acquire! = @strategy.acquire!(self) |
#can_request? ⇒ Boolean
Check if a request can be made without exceeding any limits
101 |
# File 'lib/wikiwiki/rate_limiter.rb', line 101 def can_request? = @windows.all?(&:can_request?) |
#record! ⇒ void
This method returns an undefined value.
Record a new request across all window limiters
106 |
# File 'lib/wikiwiki/rate_limiter.rb', line 106 def record! = @windows.each(&:record!) |
#wait_time ⇒ Float?
Get maximum wait time across all window limiters
111 |
# File 'lib/wikiwiki/rate_limiter.rb', line 111 def wait_time = @windows.map(&:wait_time).max |
#wait_time_until_available ⇒ Float
Get time in seconds until next request can be made
92 93 94 95 96 |
# File 'lib/wikiwiki/rate_limiter.rb', line 92 def wait_time_until_available @mutex.synchronize do @windows.map(&:wait_time).max || 0.0 end end |