#job-queue #redis #redis-queue

bin+lib rrq

RRQ orchestrator CLI and worker runtime

21 releases

Uses new Rust 2024

new 0.11.1 Mar 4, 2026
0.11.0 Mar 4, 2026
0.10.8 Feb 23, 2026
0.9.20 Feb 13, 2026
0.9.8 Jan 29, 2026

#431 in Asynchronous

Download history 82/week @ 2026-02-12 28/week @ 2026-02-19

110 downloads per month

Apache-2.0

640KB
17K SLoC

RRQ

Crates.io Documentation License

The orchestrator for RRQ, a distributed job queue that combines Rust reliability with language-flexible workers.

What is RRQ?

RRQ (Reliable Redis Queue) separates the hard parts of distributed job processing—scheduling, retries, locking, timeouts—into a single Rust binary. Your job handlers can be written in Python, TypeScript, or Rust, running as isolated processes managed by the orchestrator.

Why choose RRQ?

  • Write handlers in any language - Python, TypeScript, or Rust workers connect via socket protocol
  • Redis-native - Atomic operations, predictable semantics, no separate database to manage
  • Battle-tested Rust core - The complex distributed systems logic runs in optimized Rust
  • Production features included - Retries, DLQ, timeouts, cron scheduling, health checks, distributed tracing

Installation

cargo install rrq

Or add to your Cargo.toml:

[dependencies]
rrq = "0.9"

Quick Start

1. Create configuration (rrq.toml)

[rrq]
redis_dsn = "redis://localhost:6379/0"
default_runner_name = "python"

[rrq.runners.python]
type = "socket"
cmd = ["rrq-runner", "--settings", "myapp.runner:settings"]
tcp_port = 9000
pool_size = 4
max_in_flight = 10

2. Start the worker

rrq worker run --config rrq.toml

The orchestrator spawns runner processes, polls Redis for jobs, dispatches work, handles retries, and manages the entire lifecycle.

3. Enqueue jobs

Use the rrq-producer crate for Rust, or the Python/TypeScript clients:

use rrq_producer::Producer;

let producer = Producer::new("redis://localhost:6379/0").await?;
let job_id = producer.enqueue("my_handler", json!({"key": "value"})).await?;

CLI Commands

Worker

# Production mode
rrq worker run --config rrq.toml

# Watch mode (restarts on file changes)
rrq worker watch --config rrq.toml --path ./src

# Burst mode (exit when queue empty)
rrq worker run --config rrq.toml --burst

Queues

rrq queue list --config rrq.toml
rrq queue stats --config rrq.toml
rrq queue inspect default --config rrq.toml

Jobs

rrq job show <job-id> --config rrq.toml
rrq job list --config rrq.toml
rrq job cancel <job-id> --config rrq.toml
rrq job replay <job-id> --config rrq.toml
rrq job trace <job-id> --config rrq.toml

Dead Letter Queue

rrq dlq list --config rrq.toml
rrq dlq stats --config rrq.toml
rrq dlq inspect <job-id> --config rrq.toml
rrq dlq requeue --all --config rrq.toml

Health

rrq check --config rrq.toml

Configuration Reference

[rrq]
redis_dsn = "redis://localhost:6379/0"    # Required
default_runner_name = "python"
default_job_timeout_seconds = 300
default_max_retries = 5
heartbeat_interval_seconds = 60
runner_shutdown_term_grace_seconds = 5.0
runner_enable_inflight_cancel_hints = false

[rrq.runners.python]
type = "socket"
cmd = ["rrq-runner", "--settings", "myapp.runner:settings"]
tcp_port = 9000
pool_size = 4           # Runner processes
max_in_flight = 10      # Concurrent jobs per runner
cwd = "/app"            # Working directory (optional)

[rrq.runners.python.env]
PYTHONPATH = "/app"     # Environment variables (optional)

# Cancellation behavior:
# - Pending jobs: deterministic cancellation (`rrq job cancel`)
# - In-flight jobs: shutdown/timeout enforcement is process lifecycle based
#   (Rust orchestrator handles TERM -> grace -> KILL on Unix)
# - Cancel hints to runners are optional and disabled by default

# Cron jobs
[[rrq.cron_jobs]]
function_name = "daily_cleanup"
schedule = "0 0 9 * * *"   # 6-field cron (with seconds)
queue_name = "maintenance"

# Watch mode settings
[rrq.watch]
path = "."
include_patterns = ["*.py", "*.toml"]
ignore_patterns = [".venv/**", "dist/**"]
#
# Optional build steps (useful for compiled handlers/runners):
# - Each entry is an argv array.
# - If any command fails, the worker remains stopped until the next change.
pre_restart_cmds = [["cargo", "build"]]
pre_restart_cwd = "."

Architecture

┌─────────────────────────────────────────────────────────────┐
│                     RRQ Orchestrator                         │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────────┐  │
│  │   Worker    │  │   Worker    │  │   Cron Scheduler    │  │
│  │   Loop      │  │   Loop      │  │                     │  │
│  └──────┬──────┘  └──────┬──────┘  └──────────┬──────────┘  │
│         │                │                    │              │
│         └────────────────┼────────────────────┘              │
│                          │                                   │
│                  ┌───────▼───────┐                           │
│                  │  Redis Store  │                           │
│                  └───────┬───────┘                           │
│                          │                                   │
│              ┌───────────┴───────────┐                       │
│              │                       │                       │
│      ┌───────▼───────┐       ┌───────▼───────┐              │
│      │  Runner Pool  │       │  Runner Pool  │              │
│      │   (Python)    │       │    (Node)     │              │
│      └───────────────┘       └───────────────┘              │
└─────────────────────────────────────────────────────────────┘

Environment Variables

Variable Description
RRQ_CONFIG Path to configuration file
RRQ_REDIS_DSN Redis connection (overrides config)
RUST_LOG Log filter/level (e.g. info, debug)
RUST_LOG_FORMAT Log output format: json (default) or pretty
Crate Purpose
rrq-producer Enqueue jobs from Rust
rrq-runner Build Rust job handlers
rrq-protocol Wire protocol types
rrq-config Configuration types

Cross-Language Compatibility

The orchestrator works seamlessly with:

All use the same Redis schema and socket protocol.

License

Apache-2.0

Dependencies

~35–55MB
~861K SLoC