Install
Release archives contain a single static binary. There is no runtime dependency beyond libc, and the musl build has none at all.
$ curl -fsSLO https://cdn.reco1ogy.com/releases/recology_1.10.0_linux_amd64.tar.gz
$ tar xzf recology_1.10.0_linux_amd64.tar.gz
$ sudo install -m 0755 recology /usr/local/bin/recology
$ recology version
recology 1.10.0 (linux/amd64)
Verify the archive against the checksum file published with each release before installing on anything you care about.
Prepare the store
Recology keeps routes, leases, and dead-letter entries in Postgres 13 or newer. Create a database and a role, then let the binary apply its own schema.
$ createdb recology
$ recology migrate --store postgres://recology@db.internal:5432/recology
applied 7 migrations, schema version 7
Migrations are forward-only and take an advisory lock, so running the command from two hosts at once is safe. The second invocation waits and then reports that there is nothing to apply.
Configuration
Configuration is a single YAML file, by default
/etc/recology/recology.yaml. It validates on load.
Unknown keys are an error rather than a warning, which catches typos in
route names before they reach production.
store: postgres://recology@db.internal:5432/recology
listen: 127.0.0.1:9713
defaults:
lease: 30s
attempts: 5
backoff: exponential
jitter: true
routes:
- name: reports
workers: 4
retry_budget: 5/min
target: http://reports.internal:8080/run
- name: webhooks
workers: 16
retry_budget: 30/min
dead_letter:
enabled: true
retain: 14d
target: http://dispatch.internal:8080/send
Credentials are read from the environment first. If
RECOLOGY_STORE_URL is set it takes precedence over
the store key, so you can keep the file free of secrets and
commit it.
Your first route
A route can be created from the configuration file or directly from the command line. The command line version is useful for experimenting; commit the file version once you are happy with it.
$ recology route add reports --workers 4 --lease 30s \
--target http://reports.internal:8080/run
created route "reports"
$ recology submit reports --payload '{"month":"current"}'
queued reports/1a04f (trace 1a04f8c31e77)
Running workers
A worker process claims leases for one or more routes. Concurrency is set per route in configuration, not per worker, so adding a worker host does not change the total amount of work in flight.
$ recology worker --routes reports,webhooks
ready claiming for 2 routes, max in flight 20
Workers exit cleanly on SIGTERM. On shutdown a worker stops claiming new leases, finishes what it holds, and releases anything still outstanding. Allow a grace period at least as long as your longest lease.
systemd unit
[Unit]
Description=Recology worker
After=network-online.target
[Service]
Type=simple
User=recology
Environment=RECOLOGY_STORE_URL=postgres://recology@db.internal:5432/recology
ExecStart=/usr/local/bin/recology worker --routes reports,webhooks
Restart=on-failure
RestartSec=5
TimeoutStopSec=90
NoNewPrivileges=true
ProtectSystem=strict
PrivateTmp=true
[Install]
WantedBy=multi-user.target
Metrics
The listener exposes /metrics in Prometheus text format and
/healthz for liveness checks. Bind it to localhost and scrape
through your existing agent, or bind it to an internal interface if you
scrape centrally.
$ curl -s localhost:9713/metrics | grep lag
recology_route_lag_seconds{route="reports"} 1.4
recology_route_lag_seconds{route="webhooks"} 8.9
Lag is the metric worth alerting on. Pending depth alone is noisy, because a large batch submitted on purpose looks identical to a stalled route until you look at how old the oldest job is.
Upgrades
Replace the binary and restart. Workers on the previous version keep
working against the same schema within a minor series, so a rolling restart
needs no coordination. Across a minor version bump, run
recology migrate first and check the changelog for
migration notes.
Command reference
| Command | Description |
|---|---|
recology migrate | Apply pending schema migrations. |
recology route add|rm|list | Manage routes. |
recology submit <route> | Queue a single job. |
recology worker | Run a worker process. |
recology status | Per-route pending, leased, failed, and lag. |
recology tail <route> | Stream state transitions. |
recology lease inspect <id> | Show one job's lease detail. |
recology dlq list|replay|purge | Work with dead-letter entries. |
recology config check | Validate a configuration file and exit. |
Duration syntax
Durations accept an integer and a unit suffix: s,
m, h, or d. Compound values such as
1h30m are accepted. Rates use the form
count/unit, for example 30/min. A bare integer is
rejected rather than assumed to be seconds.