How do I schedule a job from the shell, and watch it fire?
Table of Contents
This file documents the scheduler resource at the shell, one section per
command. Every command is a subcommand of scheduler. Three of them read the
component's generated protocol; watch subscribes instead, because a job
firing is an event and not a question. The commands are hand-written: the
generated command units project one entity onto one submenu, and the operation
reads and the subscription are not shapes a generated unit carries.
1. Commands
1.1. jobs
Reads the job definitions the session can see, with each one's cron expression, action type and command. The read states no scope of its own: the session decides what is visible.
The command is shaped like this:
scheduler jobs
It is addressed at scheduler.v1.job_definitions.list.
scheduler jobs
1.2. schedule
Creates a job definition, which is what arms a job. The name and the cron expression are positional and everything else is a flag. The expression is validated before anything is sent, so a mistyped cron is refused without a round trip, and the create claims the row does not already exist, so a second run of the same name is refused rather than silently replacing the first.
--action selects the handler: execute_sql runs --command, and
nats_publish and send_mq_message read --payload. --inactive creates the
definition without arming it, which is what makes the example below safe to
run.
The command is shaped like this:
scheduler schedule <job_name> <cron> [--action <type>] [--command <sql>] [--payload <json>] [--description <text>] [--inactive] [--reason <code>]
It is addressed at scheduler.v1.job_definitions.put.
scheduler schedule shell-example "*/5 * * * *" --action execute_sql --command "select 1" --description "created by the shell script library" --inactive
1.3. remove
Deletes a definition by the name a person types. The protocol addresses a removal by identifier, so the name is resolved through a list first and a name the session cannot see is refused before anything is deleted.
The command is shaped like this:
scheduler remove <job_name>
It is addressed at scheduler.v1.job_definitions.delete, after the list that
resolves the name.
scheduler remove shell-example
1.4. instances
Reads the executions the scheduler recorded, newest first, with each one's state, when it was triggered, how long it took and why it failed when it did.
The page is ordered by time and --job filters the page the service returned,
so a narrow --limit can hide an older execution of the job being asked
about. Raise the limit to widen the page.
The command is shaped like this:
scheduler instances [--job <name>] [--limit <n>]
It is addressed at scheduler.v1.job-instances.list.
scheduler instances --limit 5
1.5. status
Reads the live status of every job the session can see: its cron expression, whether it is active, when it last ran and how that went, when it fires next, and how many of its executions are still starting.
The command is shaped like this:
scheduler status
It is addressed at scheduler.v1.status.
scheduler status
1.6. watch
Prints the execution events as they arrive, for the number of seconds asked for. This is the one command that holds the connection open: the scheduler publishes when a job fires and nothing answers a question about that, so the shell subscribes instead of asking. The default is sixty seconds and the longest it will listen is an hour.
To see the whole flow, create an armed job in one session – the schedule
example with --inactive left out – and run this in another. The running
service reloads its schedule from the definition change event, so a job created
while it runs fires at the next boundary without a restart, which is what makes
the two sessions meet.
It subscribes to scheduler.v1.job-instance-events, which the scheduler loop
publishes and which no model declares yet, because the entity it reports on has
no model of its own.
The command is shaped like this:
#+example scheduler watch [–seconds <n>] #+end_example
scheduler watch --seconds 60