Module: RubyReactor::Period
- Defined in:
- lib/ruby_reactor/period.rb
Overview
Calendar-aligned bucket helpers for ‘with_period` dedup gating.
A bucket is a deterministic string derived from the current UTC time and the configured period. Two calls in the same bucket dedup to the same Redis marker key; calls that cross a calendar boundary land in different buckets and run again.
Constant Summary collapse
- SYMBOLIC_PERIODS =
{ second: 1, minute: 60, hour: 60 * 60, day: 60 * 60 * 24, week: 60 * 60 * 24 * 7, month: 60 * 60 * 24 * 31, year: 60 * 60 * 24 * 366 }.freeze
Class Method Summary collapse
-
.bucket_id(every, now: Time.now.utc) ⇒ Object
Build the bucket id for a given period at a given moment.
- .key(base, every, now: Time.now.utc) ⇒ Object
- .period_seconds(every) ⇒ Object
-
.ttl_seconds(every) ⇒ Object
TTL for the marker.
Class Method Details
.bucket_id(every, now: Time.now.utc) ⇒ Object
Build the bucket id for a given period at a given moment. UTC, calendar aligned for symbolic periods, index-based for integer seconds.
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/ruby_reactor/period.rb', line 23 def self.bucket_id(every, now: Time.now.utc) case every when :second then now.strftime("%Y-%m-%dT%H-%M-%S") when :minute then now.strftime("%Y-%m-%dT%H-%M") when :hour then now.strftime("%Y-%m-%dT%H") when :day then now.strftime("%Y-%m-%d") when :week then now.strftime("%G-W%V") when :month then now.strftime("%Y-%m") when :year then now.strftime("%Y") when Integer raise ArgumentError, "Period seconds must be positive" unless every.positive? "i#{now.to_i / every}" else raise ArgumentError, "Unknown period: #{every.inspect}" end end |
.key(base, every, now: Time.now.utc) ⇒ Object
63 64 65 |
# File 'lib/ruby_reactor/period.rb', line 63 def self.key(base, every, now: Time.now.utc) "period:#{base}:#{bucket_id(every, now: now)}" end |
.period_seconds(every) ⇒ Object
48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/ruby_reactor/period.rb', line 48 def self.period_seconds(every) case every when Symbol SYMBOLIC_PERIODS.fetch(every) do raise ArgumentError, "Unknown period: #{every.inspect}" end when Integer raise ArgumentError, "Period seconds must be positive" unless every.positive? every else raise ArgumentError, "Unknown period: #{every.inspect}" end end |
.ttl_seconds(every) ⇒ Object
TTL for the marker. Twice the period length so the marker survives clock skew across the boundary and reliably dedups the very next attempt.
43 44 45 46 |
# File 'lib/ruby_reactor/period.rb', line 43 def self.ttl_seconds(every) base = period_seconds(every) base * 2 end |