Skip to content

Scheduler

Jobs that fire at a chosen date and time, once or on a repeating schedule: open a challenge at the start of a round, post a reminder before the freeze, close everything when the event ends.

Requires the worker

Jobs are executed by the background worker, a separate process from the API inside the app container. If it is not running, jobs simply stay pending and nothing fires. See Deployment.

The job list

Job list

Column Meaning
ID Identifier of the job, with a copy button.
Name Label given when the job was created.
Type What the job does, see Job types.
Next run When the job is due, in your local timezone, with the cron expression underneath for repeating jobs.
Status scheduled for a job still waiting, completed once a one-shot job has run, disabled for a job that is turned off.
Last run When the job last ran, on schedule or through Run now.

Creating a job

New job

Field Notes
Name Free-form label, only used in the admin panel.
Job type What the job does. The Parameters section changes with the type.
Scheduled at Date and time the job is due, entered in your local timezone. With a cron expression it becomes First run (optional): leave it empty and the first cron occurrence is used.
Repeat (cron) Optional cron expression. Empty means the job fires once. See Repeating jobs.
Active On by default. A job that is not active never fires.
Parameters Type-specific, see below.

A job needs either a date or a cron expression, and can have both.

Jobs fire on the second

Once a minute the worker queues every job due within the next minute, each one held back until its exact time. A job scheduled for 18:00:30 starts at 18:00:30, never before. The exception is a job created or moved less than a minute before it is due: it waits for the next pass, so it can start up to a minute late.

Repeating jobs

A cron expression turns a one-shot job into a repeating one. Standard 5-field syntax is accepted, and 6 fields when you need seconds, with the seconds field first. A job fires at most once a minute, so that seconds field must name a single value: 30 0 * * * * is accepted, */10 * * * * * is refused.

Expression Fires
0 0 * * * Every day at midnight.
*/5 * * * * Every five minutes.
0 9 * * 1 Every Monday at 09:00.

The field previews the next fire times as you type, and refuses to save an expression it cannot parse or that fires more than once a minute.

Which timezone applies

Cron expressions are read in the event timezone, set by ctf.timezone in Competition settings, so "every day at midnight" stays at midnight across a daylight-saving shift. Times are always displayed in the local timezone of whoever is looking at the page.

As soon as a run is queued the job is rescheduled to its next occurrence and stays scheduled. A repeating job runs until you disable or delete it; if its expression somehow becomes unparsable, the job is deactivated instead of firing at the wrong time.

Job types

toggle_challenge

Turns a challenge on or off.

New toggle_challenge job

Parameter Notes
Challenge Id The challenge to change.
Make Active On makes the challenge visible to players, off hides it.

Two jobs on the same challenge, one with Make Active on and one off, give you a release window.

send_notification

Sends the same message the Notifications page sends, at a chosen time.

New send_notification job

Parameter Notes
Title Headline shown to players.
Content Body of the message.
Is Broadcast Send to every user instead of specific teams.
Team Ids Recipients when Is Broadcast is off.

backup_database

Dumps the database to object storage, the same dump Admin → Backups takes by hand. This is how you get nightly backups without a cron job on the host.

Parameter Notes
Keep Last How many dumps to keep. Older ones are deleted after each run. Between 1 and 100, defaults to 7.

Pair it with a cron expression: 0 3 * * * with Keep Last at 7 gives you a week of nightly dumps on a prefix that never grows. See Backups for what a dump contains, and what it does not.

Pruning happens after the dump, not before

Keep Last counts scheduled backups and the ones you took by hand alike. Set it high enough that a manual backup taken before an upgrade is not swept away by that night's run. Pre-restore backups are the exception: they are never counted and never pruned.

More job types can be added by a plugin.

Job details

Opening a job shows what it will do and what it has done.

Job details

Next run and Repeat (cron) show when the job fires next and, for a repeating job, the expression driving it. Edit changes the name, schedule, cron and parameters, Disable stops a job from firing, and Delete removes it along with its history.

Run now queues a run immediately, without touching its schedule: the job still fires on its own at its next run time afterwards, and Last run moves to now. Useful for checking that the parameters are right. If a run of the job is already queued or running, nothing is queued and the button says so.

Execution history

Every run is recorded with its status and its start and completion time. Details links to the run in the task queue, which holds its log and, for a failed run, the traceback.

Status Meaning
pending Queued, or running.
success The job ran to completion.
failed The job raised an error, or the run never reported back: the worker was stopped mid-run, or the run hit its one hour limit.
skipped The job came due while a run of it was still queued or running. Runs of one job never overlap, so this occurrence is dropped.
cancelled The run was cancelled or deleted from the task queue before it finished.

A failed run is not retried. A one-shot job is retired either way, and a repeating job moves on to its next occurrence, so check the history after an important job was due. Only the last 100 runs of a job are kept.

The task queue

Admin → Task queue opens the worker's own dashboard, live: every queued, running and finished background job, scheduled jobs and plugin tasks alike, with its log. It is the place to look when a run failed, or when nothing seems to fire at all.

Failed jobs and the queue's history are kept for 30 days, then purged every night, so the Details link of an older run can come up empty.