Skip to content

Deploy workers

You’ll deploy a worker (and optionally a beat) as long-running processes next to your web app: on gisila-panel as portless process apps, or under any process manager.

  • A package with bin/worker.dart (and bin/beat.dart) as in Run workers and Periodic tasks.
  • A Redis the workers can reach, with its URL.
Terminal window
dart compile exe bin/worker.dart -o build/worker
./build/worker --namespace=shop --queues=default --concurrency=8

A compiled binary starts fast and needs no Dart SDK on the host.

On the panel, a worker is an app with no port:

  1. Create an app with the dart runtime and expose mode process (no port, no nginx, no domain; the unit is kept alive and restarted if it exits).

  2. Set the build command so the panel compiles your worker entrypoint instead of the default bin/server.dart:

    Terminal window
    mkdir -p build && dart pub get && dart compile exe bin/worker.dart -o build/app
  3. Set the start command to the binary with its flags, for example app --namespace=shop --queues=default,emails --concurrency=8.

  4. Add an environment variable REDIS_URL (for example redis://:password@10.0.0.5:6379/0). The CLIs read it, which keeps the password out of the process list.

  5. Deploy. Repeat with bin/beat.dart for a beat app if you have periodic tasks.

Run the web app as a separate web app from the same repository, with the same REDIS_URL and namespace. See the panel docs for creating apps, env vars and deployments.

Any supervisor that restarts the process and sends SIGTERM on stop works. A systemd unit:

[Service]
ExecStart=/srv/shop/worker --namespace=shop --queues=default --concurrency=8
Environment=REDIS_URL=redis://:secret@127.0.0.1:6379/0
Restart=always
TimeoutStopSec=60

In containers, run one process per container and scale the replica count.

On SIGTERM, WorkerCli stops reserving and waits up to --drain-timeout (30 s) for running tasks. Configure the process manager’s stop timeout longer than that. Tasks still running when the process dies are redelivered after the broker’s visibility timeout (Redis: 5 minutes by default).

During a rolling deploy, old and new workers run side by side. A task name that only the new code knows is put back with a delay by old workers rather than failed, so it reaches a new worker.

Beat built by BeatCli or on GisilaQueue.redis uses a Redis lock, so running it on two hosts (or overlapping during a deploy) doesn’t double-fire. Keep --lock-ttl (30 s) short enough that a standby takes over quickly.

Terminal window
REDIS_URL=... dart run gisila_queue:gisila_queue inspect --namespace=shop --queues=default,emails,dead_letter

Queue depths should stay near zero under normal load and dead_letter should not grow. Check the app’s runtime logs on the panel for worker started: queues=....