Skip to main content

A lightweight, observable job runner with a built-in web API

Project description

Jobrail

Cron jobs with visibility. Know what ran, what failed, and why.

Ofelia with memory. Sidekiq without Redis. Kubernetes CronJobs without Kubernetes.


Documentation

Full documentation is available at paracosm-lab.github.io/jobrail and in-app at localhost:8010/docs.

The problem

Every production system accumulates scheduled work: cert checks, backup verification, health sweeps, cleanup tasks, cost reports. This work isn't your application — it's the operational plumbing that keeps everything else running.

Your options today:

  • Ofelia / cron — fire and forget. No history, no API, no metrics. When a job fails silently at 3 AM, you find out from your users.
  • Celery / Sidekiq — built for distributed task queues, not a weekly cert check. You're standing up Redis, workers, and a monitoring layer for something that should be simple.
  • Kubernetes CronJobs — requires Kubernetes. State lives in pod logs. "Did my backup job actually succeed last Tuesday?" is a kubectl archaeology project.
  • Shell scripts on cron — works until it doesn't. No concurrency protection, no structured output, debugging means SSH and grep.

None of these treat observability as a first-class feature.

What Jobrail does differently

Every job execution is persisted. Jobrail writes a record to SQLite the moment a job starts running, and updates it when it finishes. Runs survive restarts. If the process dies mid-job, you'll see a status: running row with no finished_at — that's a signal, not silence.

The API makes everything programmable. List jobs, trigger a run, inspect history — all over REST. Your CI pipeline can kick off a backup verification. Your deploy script can check that health sweeps are passing. No SSH required.

Prometheus metrics are built in. jobrail_job_runs_total, jobrail_job_duration_seconds, jobrail_job_last_success_timestamp — exposed at /metrics, scraped by your existing monitoring stack, visualized in Grafana. A sample dashboard ships in the repo.

Writing a job is just Python. No framework magic. Define an async def run() function, return a JobResult, register it in one dict. That's the entire contract.

from jobs.base import JobResult

async def run() -> JobResult:
    # your logic here
    return JobResult(success=True, summary="all 5 endpoints healthy")

Quick start

With Docker Compose

git clone https://github.com/Paracosm-Lab/jobrail.git
cd jobrail
cp .env.example .env
docker compose up -d

Jobrail is running at http://localhost:8010. The two example jobs (hello-world and http-health-check) are already scheduled.

Verify it works

# List all registered jobs
curl http://localhost:8010/jobs | jq

# Trigger a job manually
curl -X POST http://localhost:8010/jobs/hello-world/trigger \
  -H "Authorization: Bearer dev-token-change-me"

# Check run history
curl http://localhost:8010/jobs/hello-world/runs | jq

# View Prometheus metrics
curl http://localhost:8010/metrics | grep jobrail_

With Kamal

A deploy template is included at config/deploy.yml. Update the server IP, registry, and secrets, then:

kamal setup

Writing your first job

See the Writing Jobs guide for the full walkthrough.

API

Endpoint Method Auth Description
/health GET No Liveness check
/metrics GET No Prometheus metrics
/jobs GET No List all jobs with status and next run time
/jobs/runs GET No Cross-job run history
/jobs/{name}/trigger POST Token Trigger a job immediately
/jobs/{name}/runs GET No Run history for a specific job
/jobs/{name}/runs/{id} GET No Single run details
/admin/info GET Token Service info, uptime, scheduler state
/admin/maintenance POST Token Pause/resume all scheduled jobs

Auth endpoints require Authorization: Bearer <SERVICE_TOKEN> header.

Configuration

See the Configuration Reference.

Monitoring

See the Monitoring guide for Prometheus metrics and Grafana setup.

How it compares

Jobrail Ofelia Celery beat k8s CronJob
Persistent run history Yes No Partial No
REST API Yes No No No
Prometheus metrics Yes No Partial No
Manual trigger Yes No Yes Yes
Concurrency protection Yes Yes Yes Partial
External dependencies None None Redis Kubernetes
Grafana dashboard included Yes No No No

Where it fits

Jobrail is not a replacement for your application's background job system. Sidekiq processes your user's uploads. Celery runs your ML pipeline. Those belong in your application.

Jobrail handles the operational layer alongside it — the cert checks, health sweeps, backup verification, and cleanup tasks that don't belong inside any one service. It's the scheduled ops work that every team does, and that most teams have cobbled together from cron entries, shell scripts, and hope.

Example jobs

See the Example Job Catalog.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

jobrail-0.3.0.tar.gz (252.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

jobrail-0.3.0-py3-none-any.whl (267.1 kB view details)

Uploaded Python 3

File details

Details for the file jobrail-0.3.0.tar.gz.

File metadata

  • Download URL: jobrail-0.3.0.tar.gz
  • Upload date:
  • Size: 252.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for jobrail-0.3.0.tar.gz
Algorithm Hash digest
SHA256 3ed9933914bdfb0a55ed16bc5d429450cae09cbba8b11f81cc6c838ec12fdf33
MD5 ea9af79b290789729d7d13f7a69784c2
BLAKE2b-256 bc3dede233c8e06a282079241eaf92eb060fdb363e7b1c926a02be0c00f2ab3b

See more details on using hashes here.

Provenance

The following attestation bundles were made for jobrail-0.3.0.tar.gz:

Publisher: publish.yml on Paracosm-Lab/jobrail

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file jobrail-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: jobrail-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 267.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for jobrail-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 711ce789d080bf51dacb4e585d96b8757d2440fe98c6eb4d172fd6574ab60edb
MD5 8940a7902573f855c423edee2000d980
BLAKE2b-256 ee3ed4feaee65b984da20a0f7dac6ae2bd29469e48e86a637e722b59a90bdd51

See more details on using hashes here.

Provenance

The following attestation bundles were made for jobrail-0.3.0-py3-none-any.whl:

Publisher: publish.yml on Paracosm-Lab/jobrail

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page