class Divider::Cron
Recurring jobs: entries of a five-field cron expression, in UTC, and a
job class (with its arguments), which a worker enqueues when they are
due (Worker.new(url, ..., cron: cron)).
cron = Divider::Cron.new([Divider::Cron.entry("*/5 * * * *", Divider::Job),
Divider::Cron.entry("@daily", Divider::Job)])
cron.due(Time.utc(2026, 11, 8, 0, 0)).size # => 2
cron.due(Time.utc(2026, 11, 8, 0, 5)).size # => 1
cron.due(Time.utc(2026, 11, 8, 0, 7)).size # => 0
Fields: minute (0-59), hour (0-23), day of the month (1-31), month (1-12
or JAN-DEC), day of the week (0-7, 0 and 7 Sunday, or SUN-SAT); each a
*, a number, a range a-b, a step */n or a-b/n, or a list of those
separated by commas. When both the day of the month and the day of the
week are restricted, a day matching either is due; a field that starts
with * (*/2 too) counts as unrestricted there, as Vixie cron and
cronie take it (0 0 */2 * MON: odd days that are Mondays).
@yearly (@annually), @monthly, @weekly, @daily (@midnight)
and @hourly stand for their usual expressions.
A worker checks every 15 seconds, by the database's clock, and enqueues each entry once per due minute however many workers check: a minute no worker checked (all of them stopped) is not made up afterwards.
/home/runner/work/divider/divider/src/cron.qz:26
Classes and modules
Divider::Cron::EntryA cron entry (Cron.entry).Divider::Cron::ScheduleThe minutes, hours, days, months and days of the week an expression matches; any_day/any_wday when those fields started with *.
Constants
CLAIM: String
(One row per entry: the last minute it was enqueued for. Only the worker that moves it forward enqueues.)
MACROS: Hash[String, String]
NO_NAMES: Hash[String, Int]
MONTHS: Hash[String, Int]
WDAYS: Hash[String, Int]
Class methods
def self.new(entries: Array[Divider::Cron::Entry]) -> Divider::Cron
A schedule of entries.
def self.entry(expression: String, job: Type[Divider::Job], **args: Object) -> Divider::Cron::Entry
An entry: job enqueued, with args (its arguments as keywords,
JSON-encoded now; checked when the job is decoded), at each minute
expression matches. ArgumentError for an expression that does not
parse.
def self.parse(expression: String) -> Divider::Cron::Schedule
The schedule of expression; ArgumentError when it does not parse.
Methods
def entries -> Array[Divider::Cron::Entry]
The entries.
def due(at: Time) -> Array[Divider::Cron::Entry]
The entries due at the minute of at (UTC; seconds ignored).