Class: Wurk::Limiter::Window
Overview
Sliding window via ZSET of timestamps. Accepts symbolic units or a raw Integer (in seconds). Used-units expand to N ZADDs in the Lua script so multi-charge calls remain atomic.
Constant Summary collapse
- WAIT_SLEEP =
0.5
Instance Attribute Summary
Attributes inherited from Base
Instance Method Summary collapse
-
#initialize(name, **options) ⇒ Window
constructor
A new instance of Window.
- #size ⇒ Object
-
#status ⇒ Object
used = entries still inside the window; limit = count; reset_at = when the oldest entry slides out (freeing a slot), or nil when idle (#16).
- #type ⇒ Object
- #within_limit(used: 1, &block) ⇒ Object
Methods inherited from Base
Constructor Details
#initialize(name, **options) ⇒ Window
Returns a new instance of Window.
15 16 17 18 19 |
# File 'lib/wurk/limiter/window.rb', line 15 def initialize(name, **) # Symbol or raw Integer (spec ยง1.2: window accepts both). Limiter.interval_seconds([:interval], allow_integer: true) super end |
Instance Method Details
#size ⇒ Object
21 22 23 24 25 26 27 |
# File 'lib/wurk/limiter/window.rb', line 21 def size cutoff = ::Time.now.to_f - interval_seconds Wurk::Limiter.redis do |c| c.call('ZREMRANGEBYSCORE', state_key, '-inf', "(#{cutoff}") c.call('ZCARD', state_key).to_i end end |
#status ⇒ Object
used = entries still inside the window; limit = count; reset_at = when the oldest entry slides out (freeing a slot), or nil when idle (#16).
32 33 34 |
# File 'lib/wurk/limiter/window.rb', line 32 def status build_status(used: size, limit: @options[:count], reset_at: oldest_expiry) end |
#type ⇒ Object
13 |
# File 'lib/wurk/limiter/window.rb', line 13 def type = :window |
#within_limit(used: 1, &block) ⇒ Object
36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/wurk/limiter/window.rb', line 36 def within_limit(used: 1, &block) raise ArgumentError, 'block required' unless block deadline = ::Time.now.to_f + @options[:wait_timeout] loop do ok, _current, _oldest = acquire(used) return block.call if ok.to_i == 1 remaining = deadline - ::Time.now.to_f raise OverLimit, self if remaining <= 0 sleep [remaining, WAIT_SLEEP].min end end |