A minimal Redis-backed job queue with workers, locking, retries, and filtering.
- Priority queues via Redis sorted sets (scores)
- Distributed locking prevents duplicate processing
- Per-worker filtering dynamically route jobs to specific workers
- Retries with poison queue failed jobs retry up to N times, then move to dead-letter
- Graceful shutdown handles SIGINT/SIGTERM cleanly
- Metrics & dashboard Prometheus endpoint + web UI with editable filters
# Add items to a queue
cmd add myqueue item1 item2 item3
# Add with priority (lower scores processed first)
cmd add myqueue --score 10 high-priority-item
cmd add myqueue --score 100 low-priority-item
# Start a worker that runs "process.sh" for each item
cmd server myqueue ./process.sh
# List queue contents
cmd list myqueue
cmd list myqueue --detail # shows which items are locked and by whom
# Start metrics dashboard
cmd metrics myqueue --port 9090cmd add <queue> [items...]
cmd add <queue> --score <n> [items...] # priority (lower = first)
cmd add <queue> --transient [items...] # pub/sub only, not persistedcmd list <queue>
cmd list <queue> --detail # show lock info
cmd list <queue> --filter <pat> # filter by substring
cmd list <queue> --number # show item count
cmd list <queue> --server # list active workers insteadcmd get <queue> <item>cmd remove <queue> <item1> <item2>
cmd remove <queue> --all # clear entire queuecmd server <queue> <command> [args...]
# Options:
# --filter <pat> only process items matching pattern
# --max-retries <n> retry failed items N times (default: 5)
# --delay-between <d> wait between items (default: 3s)
# --delay-start <d> wait before starting
# --reverse process in reverse order
# --stop-when-empty exit when queue is empty
# --transient use pub/sub mode
# --verbose print debug info
# --print print each item being processedExample:
# Process video files, only mp4s, with 10s between jobs
cmd server videos ./transcode.sh --filter .mp4 --delay-between 10scmd set-filter <queue> <server-id> <filter>
cmd set-filter <queue> <server-id> --removecmd lock <queue> --list # show locked items
cmd lock <queue> --list --detail # with timestamps
cmd lock <queue> --add <items...> # manually lock
cmd lock <queue> --remove <items...>
cmd lock <queue> --delete # clear all locks
cmd lock <queue> --prune 1h # remove locks older than 1 hourcmd stop <queue> # stop all workers on this queue
cmd stop <queue> <hostname> # stop workers on specific host
cmd stop <queue> --after 5m # stop after 5 minutescmd metrics <queue1> [queue2...] --port 9090Opens:
http://localhost:9090/- Web dashboardhttp://localhost:9090/metrics- Prometheus endpoint
The /metrics endpoint exposes Prometheus-format metrics:
| Metric | Type | Description |
|---|---|---|
cmd_queue_size{queue="..."} |
gauge | Total items in queue |
cmd_queue_active{queue="..."} |
gauge | Items currently being processed |
cmd_queue_pending{queue="..."} |
gauge | Items waiting to be processed |
cmd_queue_poison{queue="..."} |
gauge | Items in dead-letter queue |
cmd_workers_active{queue="..."} |
gauge | Number of active workers |
Example Prometheus scrape config:
scrape_configs:
- job_name: 'cmd'
static_configs:
- targets: ['localhost:9090']The dashboard at / shows for each queue:
- Metrics summary (size, pending, active, poison, workers)
- Pending items (paginated)
- Active items with server name and duration
- Workers with editable filters and cancel buttons
Auto-refreshes every 10 seconds.
| Key | Type | Purpose |
|---|---|---|
{queue} |
SET or ZSET | Queue items (ZSET if scores used) |
{queue}-active |
HASH | Locked items: item -> "server timestamp" |
{queue}-server |
ZSET | Active workers: server-id -> timestamp |
{queue}-server-filter |
HASH | Per-worker filters: server-id -> pattern |
{queue}-poison |
ZSET | Dead-letter queue: item -> timestamp |
{queue}-stop |
HASH | Stop signals |
{queue}:{item} |
HASH | Per-item retry counter |
nix develop
cargo build
cargo run -- --helpMIT