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 Attribute Summary
Attributes inherited from Base
Instance Method Summary collapse
-
#size ⇒ Object
Apply refill on read so the size matches what the next acquire would see.
-
#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
Methods inherited from Base
#delete, #fingerprint, #initialize, #reset
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 |
#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 |