Postgres-native background job queue for Rust and Python
Project description
Awa
Postgres-native background job queue for Rust and Python.
Awa (Māori: river) provides durable, transactional job enqueueing with typed handlers in both Rust and Python. The Rust runtime handles all queue machinery — polling, LISTEN/NOTIFY wakeups, heartbeating, crash recovery, dispatch — while Python workers run as callbacks via PyO3 on that same runtime, getting Rust-grade queue reliability with Python-native ergonomics.
Features
- Postgres-only — no Redis, no RabbitMQ. One dependency you already have.
- Transactional enqueue — insert jobs inside your business transaction. Commit = job exists. Rollback = it doesn't.
- Two first-class languages — Rust and Python workers on the same queues with identical semantics.
- SKIP LOCKED dispatch — efficient, contention-free job claiming.
- Heartbeat + deadline crash recovery — stale jobs rescued automatically.
- Priority aging — low-priority jobs won't starve.
- LISTEN/NOTIFY wakeup — sub-10ms pickup latency.
- OpenTelemetry metrics — built-in counters, histograms, and gauges.
Quick Start (Rust)
use awa::{Client, QueueConfig, JobArgs, JobResult, JobError, JobContext, JobRow, Worker};
use serde::{Serialize, Deserialize};
#[derive(Debug, Serialize, Deserialize, JobArgs)]
struct SendEmail {
to: String,
subject: String,
}
#[async_trait::async_trait]
impl Worker for SendEmail {
fn kind(&self) -> &'static str { "send_email" }
async fn perform(&self, job: &JobRow, ctx: &JobContext) -> Result<JobResult, JobError> {
let args: SendEmail = serde_json::from_value(job.args.clone())
.map_err(|e| JobError::terminal(e.to_string()))?;
send_email(&args.to, &args.subject).await
.map_err(JobError::retryable)?;
Ok(JobResult::Completed)
}
}
// Insert a job
awa::insert(&pool, &SendEmail {
to: "alice@example.com".into(),
subject: "Welcome".into(),
}).await?;
// Transactional insert — atomic with your business logic
let mut tx = pool.begin().await?;
create_order(&mut *tx, &order).await?;
awa::insert(&mut *tx, &SendOrderEmail { order_id: order.id }).await?;
tx.commit().await?;
// Start workers
let client = Client::builder(pool)
.queue("default", QueueConfig::default())
.register_worker(SendEmail { to: String::new(), subject: String::new() })
.build()?;
client.start().await?;
Quick Start (Python)
import awa
import asyncio
from dataclasses import dataclass
@dataclass
class SendEmail:
to: str
subject: str
client = awa.Client("postgres://localhost/mydb")
# Insert
await client.insert(SendEmail(to="alice@example.com", subject="Welcome"))
# Transactional insert — atomic with your business logic
async with await client.transaction() as tx:
await tx.execute("INSERT INTO orders (id, total) VALUES ($1, $2)", order_id, total)
await tx.insert(SendEmail(to="alice@example.com", subject="Order confirmed"))
# Commits on success, rolls back on exception
# Worker
@client.worker(SendEmail, queue="email")
async def handle(job):
await send_email(job.args.to, job.args.subject)
client.start([("email", 10)])
health = await client.health_check()
assert health.heartbeat_alive
await asyncio.sleep(10)
await client.shutdown()
Note:
async with await client.transaction()uses a double-await becausetransaction()is an async method that returns a context manager. This is inherent to the PyO3 async bridge pattern.
Setup
# Run migrations once (not on every app startup)
awa --database-url $DATABASE_URL migrate
# Or from Python:
# await awa.migrate("postgres://...")
Installation
Rust
[dependencies]
awa = "0.1"
Python
pip install awa-pg
CLI
cargo install awa-cli
awa --database-url $DATABASE_URL migrate
awa --database-url $DATABASE_URL queue stats
awa --database-url $DATABASE_URL job list --state failed
Architecture
┌────────────────────┐ ┌────────────────────┐
│ Rust producers │ │ Python producers │
│ `awa-model` / `awa`│ │ `pip install awa-pg` │
└─────────┬──────────┘ └─────────┬──────────┘
│ │
└──────────────┬────────────┘
▼
┌──────────────────────┐
│ PostgreSQL `awa.jobs`│
└──────────┬───────────┘
│
┌────────────────┼────────────────┐
│ │ │
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ Rust runtime │ │ Rust runtime │ │ Rust runtime │
│ + Rust worker │ │ + Python cb │ │ + Python cb │
│ `awa-worker` │ │ via PyO3 │ │ via PyO3 │
└───────────────┘ └───────────────┘ └───────────────┘
All coordination happens through Postgres, and the Rust runtime owns polling, heartbeats, shutdown, and crash recovery for both Rust and Python handlers. Mixed Rust and Python workers coexist on the same queues — jobs inserted from any language are workable by any language.
Workspace
| Crate | Purpose |
|---|---|
awa |
Facade — re-exports everything |
awa-model |
Types, queries, migrations, admin ops |
awa-macros |
#[derive(JobArgs)] proc macro |
awa-worker |
Runtime: dispatch, heartbeat, maintenance |
awa-python |
PyO3 extension module |
awa-testing |
Test helpers (TestClient) |
awa-cli |
CLI binary |
Documentation
- Architecture
- ADR-001: Postgres-only
- ADR-002: BLAKE3 uniqueness
- ADR-003: Heartbeat + deadline hybrid
- ADR-004: PyO3 async bridge
- ADR-005: Priority aging
- ADR-006: AwaTransaction as narrow SQL surface
- Validation test plan
License
MIT OR Apache-2.0
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file awa_pg-0.1.6-cp312-cp312-macosx_11_0_arm64.whl.
File metadata
- Download URL: awa_pg-0.1.6-cp312-cp312-macosx_11_0_arm64.whl
- Upload date:
- Size: 3.2 MB
- Tags: CPython 3.12, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1170d880b06c70c9f1c206b2d89d138b6daa9acf29c972214f3c2914091d6a7e
|
|
| MD5 |
773a5de1d242901158101d5e566a8872
|
|
| BLAKE2b-256 |
2115b29a261caa0f736856269eebd7a1b975ed77e89c4baa15d13ecbd8c38601
|
Provenance
The following attestation bundles were made for awa_pg-0.1.6-cp312-cp312-macosx_11_0_arm64.whl:
Publisher:
release.yml on hardbyte/awa
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
awa_pg-0.1.6-cp312-cp312-macosx_11_0_arm64.whl -
Subject digest:
1170d880b06c70c9f1c206b2d89d138b6daa9acf29c972214f3c2914091d6a7e - Sigstore transparency entry: 1119290626
- Sigstore integration time:
-
Permalink:
hardbyte/awa@47e42aa81b51147b156d9ad57477cecec289cdb4 -
Branch / Tag:
refs/tags/v0.1.6 - Owner: https://github.com/hardbyte
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@47e42aa81b51147b156d9ad57477cecec289cdb4 -
Trigger Event:
push
-
Statement type:
File details
Details for the file awa_pg-0.1.6-cp312-cp312-macosx_10_12_x86_64.whl.
File metadata
- Download URL: awa_pg-0.1.6-cp312-cp312-macosx_10_12_x86_64.whl
- Upload date:
- Size: 3.3 MB
- Tags: CPython 3.12, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d272037e59e9bce6009f0553f5f8a8f858fd9641c7fae2dfea0513b41dd7ac22
|
|
| MD5 |
0dff505915772ef703d2c3e4ad5b7325
|
|
| BLAKE2b-256 |
88cc295edbae0e93f02e0673bf2f4e44f34d940d4da42579c9141a04606e6b7b
|
Provenance
The following attestation bundles were made for awa_pg-0.1.6-cp312-cp312-macosx_10_12_x86_64.whl:
Publisher:
release.yml on hardbyte/awa
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
awa_pg-0.1.6-cp312-cp312-macosx_10_12_x86_64.whl -
Subject digest:
d272037e59e9bce6009f0553f5f8a8f858fd9641c7fae2dfea0513b41dd7ac22 - Sigstore transparency entry: 1119290629
- Sigstore integration time:
-
Permalink:
hardbyte/awa@47e42aa81b51147b156d9ad57477cecec289cdb4 -
Branch / Tag:
refs/tags/v0.1.6 - Owner: https://github.com/hardbyte
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@47e42aa81b51147b156d9ad57477cecec289cdb4 -
Trigger Event:
push
-
Statement type:
File details
Details for the file awa_pg-0.1.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: awa_pg-0.1.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 3.5 MB
- Tags: CPython 3.8, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
664df48fa538b268402b51bff82e4e02640e9ceaa9493d350616739273484594
|
|
| MD5 |
3b643943cb9620379ff5b8f47757d157
|
|
| BLAKE2b-256 |
80b704ab0b53785a82612dd3237e1ef7e8c06a79aff51879f97b53765a60c9cc
|
Provenance
The following attestation bundles were made for awa_pg-0.1.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
release.yml on hardbyte/awa
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
awa_pg-0.1.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
664df48fa538b268402b51bff82e4e02640e9ceaa9493d350616739273484594 - Sigstore transparency entry: 1119290619
- Sigstore integration time:
-
Permalink:
hardbyte/awa@47e42aa81b51147b156d9ad57477cecec289cdb4 -
Branch / Tag:
refs/tags/v0.1.6 - Owner: https://github.com/hardbyte
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@47e42aa81b51147b156d9ad57477cecec289cdb4 -
Trigger Event:
push
-
Statement type:
File details
Details for the file awa_pg-0.1.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: awa_pg-0.1.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 3.5 MB
- Tags: CPython 3.8, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
54b80f8acbde5a9078518b6b590eaaafa891936a4602340c43be9345e03b9ccf
|
|
| MD5 |
219c64c09d8829f1fb9e02882b50d9ec
|
|
| BLAKE2b-256 |
542bcf96a38669301c1c243b26ca08c9ff6fda2cb809a7391dafcd8e40c2375e
|
Provenance
The following attestation bundles were made for awa_pg-0.1.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:
Publisher:
release.yml on hardbyte/awa
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
awa_pg-0.1.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl -
Subject digest:
54b80f8acbde5a9078518b6b590eaaafa891936a4602340c43be9345e03b9ccf - Sigstore transparency entry: 1119290631
- Sigstore integration time:
-
Permalink:
hardbyte/awa@47e42aa81b51147b156d9ad57477cecec289cdb4 -
Branch / Tag:
refs/tags/v0.1.6 - Owner: https://github.com/hardbyte
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@47e42aa81b51147b156d9ad57477cecec289cdb4 -
Trigger Event:
push
-
Statement type: