Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@

Notable changes between releases. Detailed migration notes for storage transitions live in [`docs/upgrade-0.5-to-0.6.md`](docs/upgrade-0.5-to-0.6.md).

## [Unreleased]

### Added

- **Per-job routing in Python COPY batch APIs** ([#348](https://github.com/hardbyte/awa/pull/348), [ADR-031](docs/adr/031-partitioned-queues.md)). `insert_many_copy` / `enqueue_many_copy` (async and sync) accept `opts=[...]` entries that override `queue` and `ordering_key` per job, so one COPY call can carry a mixed-partition batch. Batch-level kwargs remain defaults; an explicit `"ordering_key": None` clears the key for that job.

### Changed

- **Breaking (beta series): `QueueFanout` is replaced by `PartitionedQueue`** ([#348](https://github.com/hardbyte/awa/pull/348), [ADR-031](docs/adr/031-partitioned-queues.md)); no compatibility alias. Besides the rename (`width` → `partitions`, `queue_fanout` → `partitioned_queue`, Python `*_per_queue` config kwargs → `*_per_partition`), routing behavior differs from beta.2: partition 0 is now the logical queue name itself (`email`, `email__p1`, ...) so direct enqueues to the logical name stay consumable, and key→partition selection uses a domain-separated hash so it composes with ADR-025 enqueue-shard routing (the same key may land on a different partition than under beta.2 `QueueFanout`). Drain fanout queues before upgrading producers/workers, or pin explicit names via `from_physical_queues`.

## [0.6.0-beta.2] — 2026-06-10

Second beta of the 0.6 line. The headline is storage-engine work under pinned MVCC horizons ([#169](https://github.com/hardbyte/awa/issues/169)): sequence-backed cursors, append-only ready segments, and a terminal-count delta ledger replace the remaining hot-row update paths that beta.1 still carried. This is also the release the #169 stable gate will be validated against — see "Benchmark evidence" below.
Expand All @@ -25,7 +35,7 @@ Migrations v022–v031 apply via `awa migrate` (or the SQL-only path in [`docs/m
- **Transactional follow-up jobs** ([ADR-029](docs/adr/029-transactional-followup-jobs.md), [#285](https://github.com/hardbyte/awa/pull/285)/[#288](https://github.com/hardbyte/awa/pull/288)). `ClientBuilder::on_completed_enqueue` (and friends) registers a follow-up job inserted in the same transaction as the lifecycle transition for worker-driven outcomes; callback resolution through the worker `Client` commits transition + follow-up atomically too. Maintenance rescue stays best-effort by design.
- **Callback-only router and user-owned callback layers** ([#291](https://github.com/hardbyte/awa/pull/291)/[#293](https://github.com/hardbyte/awa/pull/293), closes [#281](https://github.com/hardbyte/awa/issues/281)). The callback ingress contract is shared and the URL prefix configurable; embed Awa's router or implement the contract in your own API layer — axum and FastAPI examples documented.
- **`WaitingForCallback` lifecycle event + client-side callback resolution** ([#276](https://github.com/hardbyte/awa/pull/276)). Jobs parking on `WaitForCallback` are now visible to lifecycle hooks, and `Client` gains `resolve_callback` / `complete_external` / `fail_external` / `retry_external` that dispatch the matching terminal event in-process.
- **Queue fanout helper** ([#327](https://github.com/hardbyte/awa/pull/327)). Rust `QueueFanout` + `ClientBuilder::queue_fanout` and Python `awa.QueueFanout` for deterministic routing from one hot logical queue to multiple physical queues; duplicate physical declarations are rejected.
- **Queue fanout helper** ([#327](https://github.com/hardbyte/awa/pull/327)). Rust `QueueFanout` + `ClientBuilder::queue_fanout` and Python `awa.QueueFanout` for deterministic routing from one hot logical queue to multiple physical queues; duplicate physical declarations are rejected. Replaced by `PartitionedQueue` in [#348](https://github.com/hardbyte/awa/pull/348).
- **Cron schedule pause / resume** ([#320](https://github.com/hardbyte/awa/pull/320), migration v026). `POST /api/cron/{name}/pause` / `/resume`; the evaluator skips paused rows and the `atomic_enqueue` CTE re-checks `paused_at IS NULL` so a pause asserted mid-evaluation still takes effect. `last_enqueued_at` is untouched while paused, so `missed_fire_policy` decides catch-up on resume. Manual `trigger_cron_job` bypasses pause. The `/cron` UI gains Pause/Resume controls.
- **`awa storage finalize --wait` / `--check`** ([#298](https://github.com/hardbyte/awa/pull/298)). `--wait` polls and finalizes once readiness gates stay clear for two consecutive observations; `--check` is a dry-run that exits 2 when blocked.
- **Storage-transition readiness UI** ([#299](https://github.com/hardbyte/awa/pull/299)). Time-in-state, epoch-anchored backlog history, a prominent `prepared_schema_ready=false` warning with the remediation command, and a rollback-boundaries panel.
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Awa (Māori: river) fills the gap between Postgres event queues that are too nar
- A worker **claims** a job before running it. The claim increments `run_lease`, which guards completion so stale workers cannot finish a newer attempt.
- A **lease** is the durable execution record for a live attempt. Short jobs usually stay on the receipt path; jobs that need heartbeat, progress, callbacks, or mutable attempt state materialize a lease row.
- A **lane** is the ordered stream for one `(queue, priority, enqueue_shard)`. FIFO is strict inside a lane; raising shard count creates partitioned FIFO.
- A **queue fanout** maps one hot logical workload to several physical queues so workers can drain independent claim/completion streams while preserving normal Awa durability and rescue semantics.
- A **partitioned queue** maps one hot logical workload to several physical queues so workers can drain independent claim/completion streams while preserving normal Awa durability and rescue semantics.
- A **segment** is a ring partition Awa can rotate and later truncate. Segments keep high-churn queue history off long-lived row-vacuum paths.
- A **ready tombstone** is a small marker saying an immutable ready row should no longer be claimed, for example after cancelling or reprioritizing an unclaimed job. The ready row itself stays append-only until segment prune.

Expand Down Expand Up @@ -74,7 +74,7 @@ A phase-driven portable benchmark harness comparing Awa against pgque, procrasti

## Hot Queues

Queues default to one physical queue, one enqueue shard, one claimer, and one queue-storage completion shard. Those defaults are intentionally conservative. For workloads that need more end-to-end throughput and can accept partitioned ordering, Rust and Python both expose `QueueFanout` to route one logical queue over several physical queues. `enqueue_shards` and `claimers` address different bottlenecks; see [Choosing a throughput lever](docs/configuration.md#choosing-a-throughput-lever) before changing them.
Queues default to one physical queue, one enqueue shard, one claimer, and one queue-storage completion shard. Those defaults are intentionally conservative. For workloads that need more end-to-end throughput and can accept partitioned ordering, Rust and Python both expose `PartitionedQueue` to route one logical queue over several physical queues. `enqueue_shards` and `claimers` address different bottlenecks; see [Choosing a throughput lever](docs/configuration.md#choosing-a-throughput-lever) before changing them.

Methodology and caveats live in [benchmarking notes](docs/benchmarking.md). Validation artifacts: [ADR-019 (queue storage)](docs/adr/bench/019-queue-storage-validation-2026-04-19.md) and [ADR-023 (receipt-plane ring partitioning)](docs/adr/bench/023-receipt-ring-validation-2026-04-26.md).

Expand Down
2 changes: 1 addition & 1 deletion awa-model/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Most Rust applications should depend on the [`awa`](https://crates.io/crates/awa

- **Job model** — `JobRow`, `JobState`, `InsertOpts`, `UniqueOpts`, `InsertParams`.
- **Insertion** — `insert`, `insert_with`, `insert_many`, `insert_many_copy` for the compatibility insert surface, and `QueueStorage::enqueue_params_copy` for direct queue-storage COPY ingestion with an explicitly configured queue-storage engine.
- **Queue fanout** — `QueueFanout` gives enqueue-only producers the same deterministic physical queue routing workers use for very hot logical queues.
- **Partitioned queues** — `PartitionedQueue` gives enqueue-only producers the same deterministic physical queue routing workers use for very hot logical queues.
- **Migrations** — `migrations::run` applies the schema; `migrations`, `migration_sql`, `migration_sql_range`, and `current_version` expose the catalog for tooling.
- **Admin** (`admin`) — retry, cancel (single, by unique key, bulk), pause/resume/drain queues, queue and job-kind overviews, runtime instance snapshots, dirty-key recompute, and descriptor sync (`sync_queue_descriptors`, `sync_job_kind_descriptors`, `cleanup_stale_descriptors`).
- **Dead Letter Queue** (`dlq`) — `DlqRow`, `DlqMetadata`, `ListDlqFilter`, `RetryFromDlqOpts`, list / retry / move / purge helpers backing the `awa dlq` CLI and the DLQ admin UI tab.
Expand Down
6 changes: 4 additions & 2 deletions awa-model/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub mod insert;
pub mod job;
pub mod kind;
pub mod migrations;
pub mod queue_fanout;
pub mod partitioned_queue;
pub mod queue_storage;
pub mod storage;
pub mod unique;
Expand Down Expand Up @@ -39,7 +39,9 @@ pub use dlq::{DlqMetadata, DlqRow, ListDlqFilter, RetryFromDlqOpts};
pub use error::{map_sqlx_error, AwaError};
pub use insert::{insert, insert_many, insert_many_copy, insert_many_copy_from_pool, insert_with};
pub use job::{InsertOpts, InsertParams, JobRow, JobState, UniqueOpts};
pub use queue_fanout::{QueueFanout, QueueFanoutError};
pub use partitioned_queue::{
partition_for_ordering_key, partition_hash64, PartitionedQueue, PartitionedQueueError,
};
pub use queue_storage::{
ClaimedEntry, ClaimedRuntimeJob, PruneOutcome, QueueCounts, QueueStorage, QueueStorageConfig,
RotateOutcome, SkipReason, TerminalDeltaRollupOutcome,
Expand Down
Loading