Class: Wurk::Cron::Parser

Inherits:
Object
  • Object
show all
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

Instance Method Summary collapse

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

#expressionObject (readonly)

Returns the value of attribute expression.



71
72
73
# File 'lib/wurk/cron.rb', line 71

def expression
  @expression
end

#fieldsObject (readonly)

Returns the value of attribute fields.



71
72
73
# File 'lib/wurk/cron.rb', line 71

def fields
  @fields
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.



102
103
104
# File 'lib/wurk/cron.rb', line 102

def local_components(epoch, tz = nil)
  wall_clock(epoch, tz)
end

#match?(time, tz = nil) ⇒ Boolean

Returns:

  • (Boolean)


95
96
97
# File 'lib/wurk/cron.rb', line 95

def match?(time, tz = nil)
  match_components?(wall_clock(time.to_i, tz))
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