Shaperail includes a Redis-backed job queue and worker primitives. The runtime can enqueue jobs from endpoint declarations, but the scaffolded app does not start a worker or register job handlers for you.

What the scaffold does today

When Redis is configured, the generated app creates a JobQueue and write endpoints that declare jobs: will enqueue named jobs after a successful write.

Example:

endpoints:
  create:
    method: POST
    path: /users
    auth: [admin]
    input: [email, name, role, org_id]
    jobs: [send_welcome_email]

That enqueue step is automatic.

What is not automatic:

  • registering Rust job handlers
  • starting shaperail_runtime::jobs::Worker
  • processing retries and dead-letter transitions

Wiring a worker manually

To actually execute queued jobs, create a registry and spawn a worker from your app bootstrap:

use std::collections::HashMap;
use std::sync::Arc;
use std::time::Duration;

use shaperail_runtime::jobs::{JobRegistry, Worker};

let mut handlers = HashMap::new();
handlers.insert(
    "send_welcome_email".to_string(),
    Arc::new(|payload| Box::pin(async move {
        println!("job payload: {payload}");
        Ok(())
    })),
);

let registry = JobRegistry::from_handlers(handlers);
let worker = Worker::new(job_queue.clone(), registry, Duration::from_secs(1));
let (_tx, rx) = tokio::sync::watch::channel(false);
let _handle = worker.spawn(rx);

Queue behavior

The runtime worker polls queues in strict priority order:

Priority Redis key
critical shaperail:jobs:queue:critical
high shaperail:jobs:queue:high
normal shaperail:jobs:queue:normal
low shaperail:jobs:queue:low

Jobs declared via endpoint jobs: are enqueued at normal priority.

Retry and dead-letter behavior

Retries and dead-letter handling are worker features. Once a worker is running:

  • failed jobs are retried with exponential backoff
  • timed-out or exhausted jobs move to shaperail:jobs:dead
  • metadata is stored under shaperail:jobs:meta:{job_id}

Without a worker, jobs remain queued and never transition beyond pending.

Monitoring

The CLI can inspect queue state whether or not a worker is running:

shaperail jobs:status
shaperail jobs:status <job_id>

The summary view prints queue depth by priority, dead-letter count, and recent dead-letter entries. Passing a job ID shows the stored metadata hash for that job.

Practical guidance

  • Use jobs: when the side effect can happen after the HTTP response.
  • Do not assume declaring jobs: also creates or registers the handler.
  • In a scaffolded app, “jobs stuck in pending” usually means no worker was started.
  • Keep handlers idempotent because retries are part of the queue model.

Back to top

Shaperail documentation lives in the same repository as the framework so every release has versioned instructions. See the latest release for the most recent version.

This site uses Just the Docs, a documentation theme for Jekyll.