crontab: cron-like scheduling
| (require crontab) | package: crontab-lib | 
This package provides functionality for scheduling work inside of Racket using cron-like syntax.
1 Reference
1.1 Crontabs
syntax
(crontab [schedule-expr handler-expr] ...+) 
schedule-expr : string? 
handler-expr : (-> exact-integer? any) 
Handlers are executed synchronously within each thread, meaning procedures that take a long time to execute may cause runs to be skipped.
> (define stop (crontab ["* * * * * *" println])) 1755477161
> (sleep 5) 
1755477162
1755477163
1755477164
1755477165
1755477166
> (stop) 
The spawned threads log information about what is currently being run to the “crontab” topic.
Changed in version 0.2 of package crontab-lib: Extended logging.
1.2 Schedules
Schedules constrain the components of a timestamp to match specific moments in time.
Schedules can be used as synchronizable events. A schedule is ready for synchronization when the value of (current-seconds) is less than or equal to the value of (schedule-next s) as of the moment the event is synchronized on. The synchronization result of a schedule is the schedule itself and the timestamp (in seconds) it became ready for synchronization at.
> (require racket/date) 
> (define (~date ts) (parameterize ([date-display-format 'iso-8601]) (date->string (seconds->date ts) #t))) > 
> (define now (find-seconds 30 21 10 19 8 2022)) > > (~date now) "2022-08-19T10:21:30"
> (~date (schedule-next (parse-schedule "* * * * * *") now)) "2022-08-19T10:21:30"
> (~date (schedule-next (parse-schedule "* * * * *") now)) "2022-08-19T10:22:00"
> (~date (schedule-next (parse-schedule "0 5-23/5 * * *") now)) "2022-08-19T15:00:00"
> (~date (schedule-next (parse-schedule "0 12 * * 5") now)) "2022-08-19T12:00:00"
> (~date (schedule-next (parse-schedule "* * 29 2 *") now)) "2024-02-29T00:00:00"
> 
> (let ([s (parse-schedule "0 * * * *")]) (for/fold ([ts now]) ([_ (in-range 10)]) (define new-ts (schedule-next s ts)) (displayln (~date new-ts)) (add1 new-ts))) 
2022-08-19T11:00:00
2022-08-19T12:00:00
2022-08-19T13:00:00
2022-08-19T14:00:00
2022-08-19T15:00:00
2022-08-19T16:00:00
2022-08-19T17:00:00
2022-08-19T18:00:00
2022-08-19T19:00:00
2022-08-19T20:00:00
1660939201
> > (sync (parse-schedule "* * * * * *")) 
#<schedule>
1755477166
procedure
(parse-schedule s [local-time?]) → schedule?
s : string? local-time? : boolean? = #t 
- “@” commands are not supported, 
- “0” is not a valid weekday, and 
- month and weekday names are not supported. 
When a schedule contains 6 fields instead of 5, the first field is treated as a constraint on the seconds component of a timestamp.
Timestamps are processed by the schedule according to the local time zone if local-time? is #t and UTC otherwise.
procedure
(schedule-matches? s timestamp) → boolean?
s : schedule? timestamp : exact-integer? 
procedure
(schedule-next s [start-timestamp]) → exact-integer?
s : schedule? start-timestamp : exact-integer? = (current-seconds) 
procedure
(schedule->string s) → string?
s : schedule?