crontab:   cron-like scheduling
1 Reference
1.1 Crontabs
crontab
1.2 Schedules
schedule?
parse-schedule
schedule-matches?
schedule-next
schedule->string
8.12

crontab: cron-like scheduling🔗ℹ

Bogdan Popa <bogdan@defn.io>

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)
Spawns a thread for every entry in the table, where each thread synchronizes on the schedule and executes its associated handler procedure when the schedule is ready for synchronization. Returns a procedure that stops all the threads when applied.

Handlers are executed synchronously within each thread, meaning procedures that take a long time to execute may cause runs to be skipped.

Examples:
> (define stop
   (crontab
    ["* * * * * *" println]))

1707271778

> (sleep 5)

1707271779

1707271780

1707271781

1707271782

1707271783

> (stop)

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.

Examples:
> (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>

1707271783

procedure

(schedule? v)  boolean?

  v : any/c
Returns #t when v is a schedule.

procedure

(parse-schedule s [local-time?])  schedule?

  s : string?
  local-time? : boolean? = #t
Parses the cron schedule represented by s and returns a schedule. Supports the same syntax as BSD cron, with the following differences:

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?
Returns #t when timestamp matches the schedule.

procedure

(schedule-next s [start-timestamp])  exact-integer?

  s : schedule?
  start-timestamp : exact-integer? = (current-seconds)
Returns a timestamp representing the first moment that matches the schedule including and after start-timestamp.

procedure

(schedule->string s)  string?

  s : schedule?
Returns a representation of the schedule in cron format.