Class: Do::Scheduler
- Inherits:
-
Object
- Object
- Do::Scheduler
- Defined in:
- lib/do/scheduler.rb
Overview
Translates a task's declarative schedule into a systemd calendar
expression (#on_calendar) suitable for use in an OnCalendar= directive.
do does not implement its own timer loop; it only maps a small, fixed set
of schedule shapes onto systemd's native calendar syntax.
Constant Summary collapse
- TIME_RE =
/\A([01]?\d|2[0-3]):([0-5]\d)\z/
Class Method Summary collapse
- .daily_calendar(task) ⇒ Object
- .hourly_calendar(task) ⇒ Object
- .monthly_calendar(task) ⇒ Object
- .monthly_day(task) ⇒ Object
-
.on_calendar(task) ⇒ String?
The systemd OnCalendar expression, or nil when the task is manual-only.
- .once_calendar ⇒ Object
- .pad(value) ⇒ Object
- .split_time(task, fallback:) ⇒ Object
- .weekday_number(task) ⇒ Object
- .weekday_short(task) ⇒ Object
- .weekly_calendar(task) ⇒ Object
Class Method Details
.daily_calendar(task) ⇒ Object
39 40 41 42 |
# File 'lib/do/scheduler.rb', line 39 def self.daily_calendar(task) hour, min = split_time(task, fallback: [0, 0]) "*-*-* #{pad(hour)}:#{pad(min)}:00" end |
.hourly_calendar(task) ⇒ Object
34 35 36 37 |
# File 'lib/do/scheduler.rb', line 34 def self.hourly_calendar(task) _, min = split_time(task, fallback: [0, 0]) "*-*-* *:#{pad(min)}:00" end |
.monthly_calendar(task) ⇒ Object
50 51 52 53 54 |
# File 'lib/do/scheduler.rb', line 50 def self.monthly_calendar(task) hour, min = split_time(task, fallback: [0, 0]) dom = monthly_day(task) "*-*-#{dom} #{pad(hour)}:#{pad(min)}:00" end |
.monthly_day(task) ⇒ Object
69 70 71 72 73 74 75 76 77 78 |
# File 'lib/do/scheduler.rb', line 69 def self.monthly_day(task) day = task.day&.to_s if day.nil? || day.empty? '1' elsif day =~ /\A([1-9]|[12]\d|3[01])\z/ day else raise Error, "invalid monthly day '#{task.day}'; expected a day-of-month 1-31" end end |
.on_calendar(task) ⇒ String?
Returns the systemd OnCalendar expression, or nil when the task is manual-only.
14 15 16 17 18 19 20 21 22 23 24 25 |
# File 'lib/do/scheduler.rb', line 14 def self.on_calendar(task) case task.schedule when nil, '' then nil when 'once' then once_calendar when 'hourly' then hourly_calendar(task) when 'daily' then daily_calendar(task) when 'weekly' then weekly_calendar(task) when 'monthly' then monthly_calendar(task) else raise Error, "unsupported schedule '#{task.schedule}'" end end |
.once_calendar ⇒ Object
27 28 29 30 31 32 |
# File 'lib/do/scheduler.rb', line 27 def self.once_calendar # OnActiveSec=0 fires the service exactly once, when the timer is # activated. The reload/enable workflow activates the timer, so `once` # means "run once now when scheduled", without repeating. 'OnActiveSec=0' end |
.pad(value) ⇒ Object
89 90 91 |
# File 'lib/do/scheduler.rb', line 89 def self.pad(value) value.to_s.rjust(2, '0') end |
.split_time(task, fallback:) ⇒ Object
80 81 82 83 84 85 86 87 |
# File 'lib/do/scheduler.rb', line 80 def self.split_time(task, fallback:) return fallback if task.time.nil? || task.time.empty? m = TIME_RE.match(task.time.to_s) raise Error, "invalid time '#{task.time}'; expected HH:MM" unless m [m[1].to_i, m[2].to_i] end |
.weekday_number(task) ⇒ Object
63 64 65 66 67 |
# File 'lib/do/scheduler.rb', line 63 def self.weekday_number(task) day = task.day&.to_s&.downcase Task::WEEKDAY_NUMBERS[day] or raise Error, "invalid day '#{task.day}'; expected a day name like 'monday'" end |
.weekday_short(task) ⇒ Object
56 57 58 59 60 61 |
# File 'lib/do/scheduler.rb', line 56 def self.weekday_short(task) day = task.day&.to_s&.downcase Task::WEEKDAY_NUMBERS[day] or raise Error, "invalid day '#{task.day}'; expected a day name like 'monday'" day[0, 3].capitalize end |
.weekly_calendar(task) ⇒ Object
44 45 46 47 48 |
# File 'lib/do/scheduler.rb', line 44 def self.weekly_calendar(task) hour, min = split_time(task, fallback: [0, 0]) dow = weekday_short(task) "#{dow} *-*-* #{pad(hour)}:#{pad(min)}:00" end |