Class: Wurk::Cron::Parser
- Inherits:
-
Object
- Object
- Wurk::Cron::Parser
- Defined in:
- lib/wurk/cron.rb
Overview
5-field crontab + ‘@aliases`. No seconds field, no DOW name aliases (sidekiq-ent §2.2 uses numeric DOW only).
Constant Summary collapse
- FIELDS =
[ [0, 59], [0, 23], [1, 31], [1, 12], [0, 7] ].freeze
- ALIASES =
{ '@hourly' => '0 * * * *', '@daily' => '0 0 * * *', '@midnight' => '0 0 * * *', '@weekly' => '0 0 * * 0', '@monthly' => '0 0 1 * *', '@yearly' => '0 0 1 1 *', '@annually' => '0 0 1 1 *' }.freeze
- MAX_LOOKAHEAD_MINUTES =
366 * 24 * 60 * 4
Instance Attribute Summary collapse
-
#expression ⇒ Object
readonly
Returns the value of attribute expression.
-
#fields ⇒ Object
readonly
Returns the value of attribute fields.
Class Method Summary collapse
Instance Method Summary collapse
-
#initialize(expression) ⇒ Parser
constructor
A new instance of Parser.
-
#local_components(epoch, tz = nil) ⇒ Object
Local wall-clock [min, hour, day, mon, dow] for ‘epoch` in `tz`.
- #match?(time, tz = nil) ⇒ Boolean
-
#next(from = ::Time.now, tz = nil) ⇒ Object
Sidekiq Ent ‘Sidekiq::CronParser#next`: the next fire Time strictly after `from` (default now), or nil if the schedule never matches within the lookahead window.
-
#next_fire_at(from_epoch, tz = nil) ⇒ Object
Smallest UTC epoch strictly greater than ‘from_epoch` whose wall-clock components in `tz` match every field.
Constructor Details
#initialize(expression) ⇒ Parser
Returns a new instance of Parser.
73 74 75 76 77 78 79 |
# File 'lib/wurk/cron.rb', line 73 def initialize(expression) parts = normalize_expression(expression) @expression = parts.join(' ') @fields = parts.each_with_index.map { |part, i| parse_field(part, *FIELDS[i]) } @dom_restricted = parts[2] != '*' @dow_restricted = parts[4] != '*' end |
Instance Attribute Details
#expression ⇒ Object (readonly)
Returns the value of attribute expression.
71 72 73 |
# File 'lib/wurk/cron.rb', line 71 def expression @expression end |
#fields ⇒ Object (readonly)
Returns the value of attribute fields.
71 72 73 |
# File 'lib/wurk/cron.rb', line 71 def fields @fields end |
Class Method Details
.resolve_zone(name) ⇒ Object
230 231 232 233 234 235 236 237 |
# File 'lib/wurk/cron.rb', line 230 def resolve_zone(name) cached = @tz_cache[name] return cached || nil unless cached.nil? @tz_cache_mutex.synchronize do @tz_cache.fetch(name) { @tz_cache[name] = load_zone(name) } || nil end end |
Instance Method Details
#local_components(epoch, tz = nil) ⇒ Object
Local wall-clock [min, hour, day, mon, dow] for ‘epoch` in `tz`. Public so the Loop/Poller can detect a DST fall-back fold — two distinct UTC instants that share the same local minute — and avoid a double-fire.
112 113 114 |
# File 'lib/wurk/cron.rb', line 112 def local_components(epoch, tz = nil) wall_clock(epoch, tz) end |
#match?(time, tz = nil) ⇒ Boolean
105 106 107 |
# File 'lib/wurk/cron.rb', line 105 def match?(time, tz = nil) match_components?(wall_clock(time.to_i, tz)) end |
#next(from = ::Time.now, tz = nil) ⇒ Object
Sidekiq Ent ‘Sidekiq::CronParser#next`: the next fire Time strictly after `from` (default now), or nil if the schedule never matches within the lookahead window. `tz` evaluates the schedule in a timezone (an AS::TimeZone / TZInfo::Tz / IANA String); default is UTC. Thin wrapper over `next_fire_at` so there’s a single crontab parser.
100 101 102 103 |
# File 'lib/wurk/cron.rb', line 100 def next(from = ::Time.now, tz = nil) epoch = next_fire_at(from.to_i, tz) epoch && ::Time.at(epoch) end |
#next_fire_at(from_epoch, tz = nil) ⇒ Object
Smallest UTC epoch strictly greater than ‘from_epoch` whose wall-clock components in `tz` match every field. Returns nil if no match within ~4 years (a malformed loop like Feb 29 in a non-leap span).
84 85 86 87 88 89 90 91 92 93 |
# File 'lib/wurk/cron.rb', line 84 def next_fire_at(from_epoch, tz = nil) t = ((from_epoch.to_i / 60) + 1) * 60 MAX_LOOKAHEAD_MINUTES.times do wc = wall_clock(t, tz) return t if match_components?(wc) t += 60 end nil end |