Workers and scheduled jobs
berth_hello_python has a worker and two cron jobs if you want to see both working.
Workers
Background processes go in the Procfile, next to the web process:
web: node server.js
worker: node worker.js
clock: node clock.js
Anything other than web and release is a worker. Each one runs as
another process inside the app's container, with the same build, config and
storage, and gets restarted (with backoff) if it exits. Workers move to each
new release as it goes live, follow rollbacks, and stop and start with the
app. The old release's workers stop before the new ones start, so a job never
gets picked up twice. Each knows its name from BERTH_PROCESS (worker.2).
You
still need a web process, and it's always the image's own command: Berth
doesn't read the web: line, so it's fine to keep it for other tools.
berth ps:scale myapp worker=3 # three of them
berth ps:scale myapp clock=0 # none
berth status myapp # each worker and how long it's been up
berth logs myapp -f # worker lines say which: v4 worker.2: …
Workers share the app's memory and CPUs, so if they're heavy, give the app
more with BERTH_MEMORY and BERTH_CPUS. The image needs /bin/sh, tr
and grep, which every common base image has.
Scheduled jobs
Put a cron list in app.json at the root of the repo, in
Dokku's format:
{
"cron": [
{ "command": "node digest.js", "schedule": "0 7 * * *" },
{ "command": "python cleanup.py", "schedule": "@hourly" }
]
}
Schedules are ordinary five-field cron (minute hour day month weekday, with
ranges, steps, lists and names like mon-fri) or @hourly, @daily,
@weekly and @monthly, in the Mac's local time. They ship with the code, so
a rollback brings back the schedule that went with it, and a typo fails the
deploy rather than quietly never running.
Each run is a fresh container from the current release, with the app's
config and storage. If a job is still running when its next turn comes round,
that turn is skipped. When a job starts failing you get one notification,
and another when it works again, not one per run (a job that runs every
minute would otherwise send sixty an hour). BERTH_CRON_TIMEOUT (an hour by
default) stops runaways. Runs missed while the Mac was off don't get made up.
berth cron myapp # the jobs, when they next run and how the last run went
berth cron:run myapp 1 # run job 1 now and wait for it
berth logs myapp --cron # every run's output
Dev versions and previews don't run schedules. A job running against a copy
of production's data could email real people. Try one by hand with
berth cron:run myapp-dev 1.