pg-jobs (0.1.0)
Installation
[registries.forgejo]
index = "sparse+ " # Sparse index
# index = " " # Git
[net]
git-fetch-with-cli = truecargo add pg-jobs@0.1.0 --registry forgejoAbout this package
pg-jobs
A Postgres-native job & flow engine for Rust: DAG flows, retry/DLQ, typed
handlers, recurring scheduler, and a worker driven by LISTEN/NOTIFY (with a
polling fallback). All state lives in a dedicated jobs schema in your own
Postgres database — no external broker.
Features
- Typed handlers — implement the
Jobtrait with typedInput/Output. - DAG flows — compose jobs with dependencies (
Flow,submit_flow,rerun_flow), fan-out, and per-node dedup keys. - Retry / DLQ — configurable backoff strategies; fatal vs. retryable errors.
- Transactional execution — handlers can run inside the job's own
transaction (
ExecMode::Transactional), committing work atomically with completion. - Recurring scheduler —
every_msschedules driven from the worker loop. - Tracking — read API for flow views, queue stats, and job listing.
- No compile-time DB — uses runtime
sqlxqueries, so it builds without aDATABASE_URLor.sqlxcache.
Install
Released versions are published to the Forgejo Cargo registry. Declare the
registry in your project's .cargo/config.toml:
[registries.forgejo]
index = "sparse+https://forge.netserv.fr/api/packages/AzSiAz/cargo/"
Then depend on it in Cargo.toml:
[dependencies]
pg-jobs = { version = "0.1", registry = "forgejo" }
Authenticate once for read access with cargo login --registry forgejo
(paste a Forgejo token in the Bearer <token> form when prompted).
Alternatively, track main directly via git:
[dependencies]
pg-jobs = { git = "ssh://git@git.netserv.fr/AzSiAz/pg-jobs.git", branch = "main" }
The library crate is imported as pg_jobs.
Migrations
The crate ships its schema migrations and exposes a Migrator. Run it once at
startup; the jobs schema is created automatically.
pg_jobs::MIGRATOR.run(&pool).await?;
Usage
use pg_jobs::{Job, JobError, JobSpec, Registry, Worker, WorkerConfig};
use pg_jobs::ctx::Ctx;
use pg_jobs::store::JobStore;
use std::sync::Arc;
use std::time::Duration;
// 1. Define a typed job.
struct SendEmail;
#[async_trait::async_trait]
impl Job for SendEmail {
const KIND: &'static str = "send_email";
const QUEUE: &'static str = "default";
type Input = String; // recipient address
type Output = ();
async fn run(&self, to: String, _ctx: &mut Ctx<'_>) -> Result<(), JobError> {
// ... do the work; map errors with JobError::retryable / JobError::fatal
println!("sending to {to}");
Ok(())
}
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let pool = sqlx::PgPool::connect(&std::env::var("DATABASE_URL")?).await?;
// 2. Apply migrations.
pg_jobs::MIGRATOR.run(&pool).await?;
// 3. Register handlers and start a worker.
let store = JobStore::new(pool.clone());
let mut reg = Registry::new();
reg.register(SendEmail);
let worker = Worker::new(
store.clone(),
Arc::new(reg),
WorkerConfig {
queues: vec!["default".into()],
poll_interval: Duration::from_millis(500),
..Default::default()
},
);
// 4. Enqueue work.
store
.enqueue(JobSpec::for_job::<SendEmail>("alice@example.com".into())?)
.await?;
// 5. Run until a shutdown signal is received.
let (_tx, rx) = tokio::sync::watch::channel(false);
worker.run(rx).await?;
Ok(())
}
See the crate's tests/ directory for flows, fan-out, transactional jobs,
recurring schedules, the reaper, and tracking.
Development
A compose.yaml provides a local Postgres 18 (with extensions baked in) for
running the test suite:
docker compose up -d
export DATABASE_URL="postgres://postgres:postgres@localhost:5432/pg_jobs"
cargo test
The integration tests use #[sqlx::test], which connects to the base database
and creates/drops an isolated temporary database per test — so the configured
role must be a superuser (the default postgres user is). The crate builds
without a database (cargo build / cargo check); only the tests need one.
License
MIT © Stephan Deumier
Dependencies
| ID | Version |
|---|---|
| anyhow | ^1 |
| async-trait | ^0.1 |
| chrono | ^0.4 |
| serde | ^1 |
| serde_json | ^1 |
| sqlx | ^0.9 |
| thiserror | ^2 |
| tokio | ^1 |
| tracing | ^0.1 |
| uuid | ^1 |
| sqlx | ^0.9 |
| tokio | ^1 |