Class: Wurk::Limiter::Points
Overview
Token-bucket with explicit estimate: per call. Refills at
refill_per_second capped at initial_points. Failure mode is
immediate (spec ยง1.4 โ no sleep loop). The block is invoked with a
Handle so user code may refund/over-charge via handle.points_used.
Defined Under Namespace
Classes: Handle
Instance Method Summary collapse
-
#size ⇒ Object
Apply refill on read so the size matches what the next acquire would see.
- #state_keys ⇒ Object protected
-
#status ⇒ Object
used = points consumed (cap โ available); limit = the cap; reset_at = when the bucket refills to full, or nil when already full (#16).
- #type ⇒ Object
- #within_limit(estimate:, &block) ⇒ Object
Constructor Details
This class inherits a constructor from Wurk::Limiter::Base
Instance Method Details
#size ⇒ Object
Apply refill on read so the size matches what the next acquire would see. Stored balance only updates on acquire/refund; without this, a fully-refilled bucket reports stale low numbers.
31 32 33 34 35 36 37 38 39 40 |
# File 'lib/wurk/limiter/points.rb', line 31 def size cap = @options[:initial].to_f data = Wurk::Limiter.redis { |c| c.call('HMGET', state_key, 'points', 'last') } stored = data[0] return cap if stored.nil? last = (data[1] || ::Time.now.to_f).to_f elapsed = [::Time.now.to_f - last, 0.0].max [cap, stored.to_f + (elapsed * @options[:refill].to_f)].min end |
#state_keys ⇒ Object (protected)
66 67 68 |
# File 'lib/wurk/limiter/points.rb', line 66 def state_keys [state_key] end |
#status ⇒ Object
used = points consumed (cap โ available); limit = the cap; reset_at = when the bucket refills to full, or nil when already full (#16).
44 45 46 47 48 49 50 51 |
# File 'lib/wurk/limiter/points.rb', line 44 def status cap = @options[:initial].to_f available = size used = cap - available refill = @options[:refill].to_f reset_at = available < cap && refill.positive? ? ::Time.now.to_f + ((cap - available) / refill) : nil build_status(used: used, limit: cap, reset_at: reset_at) end |
#type ⇒ Object
26 |
# File 'lib/wurk/limiter/points.rb', line 26 def type = :points |
#within_limit(estimate:, &block) ⇒ Object
53 54 55 56 57 58 59 60 61 62 |
# File 'lib/wurk/limiter/points.rb', line 53 def within_limit(estimate:, &block) raise ArgumentError, 'block required' unless block raise ArgumentError, 'estimate must be positive' if estimate <= 0 ok, _remaining = acquire(estimate) raise OverLimit, self unless ok.to_i == 1 handle = Handle.new(self, estimate) block.call(handle) end |