Skip to main content

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

Project description

Jobrail

A lightweight job runner with persistent history, a built-in API, and Prometheus metrics. One container, one SQLite file, zero infrastructure dependencies.

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.2.0.tar.gz (207.3 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.2.0-py3-none-any.whl (223.1 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for jobrail-0.2.0.tar.gz
Algorithm Hash digest
SHA256 71318d2ac1bc3662d238278c24b33df5d4026b9c51de8832fba5a8c89294eb5e
MD5 f0e7d322e5c398e1810137a461156597
BLAKE2b-256 40af1432b1b4a5803b57e6750be6af441c70f831b04c54a5418f032948314ecb

See more details on using hashes here.

Provenance

The following attestation bundles were made for jobrail-0.2.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.2.0-py3-none-any.whl.

File metadata

  • Download URL: jobrail-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 223.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.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d0af87961510d400d1ed749f6166b6f4b6d3737f521054470197921ab04c3aa3
MD5 ff06af2e8c3b079d898d939ce88cf44c
BLAKE2b-256 9c0fbbfbb384bd1fe7cf64cfa28c47e1a2abd7f48f8db855af35e096086675f9

See more details on using hashes here.

Provenance

The following attestation bundles were made for jobrail-0.2.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