Skip to content

fix(worker): bound finalization backlog and key metadata completions (0.6) - #695

Merged
hardbyte merged 6 commits into
release/0.6.6from
brian/bounded-finalization-0.6
Nov 8, 2026
Merged

hardbyte merged 6 commits into
release/0.6.6from
brian/bounded-finalization-0.6

Conversation

@hardbyte

@hardbyte hardbyte commented Nov 8, 2026 •

Copy link
Copy Markdown
Owner

Carries #686 by @JosiahBull onto the current release/0.6.6, so CI runs in this repository, and supersedes #686 and #648. Jo's two commits are unchanged.

Summary

When handlers finish faster than completions commit, detached finalizers pile up without bound, each holding its job's payload. Under a 120 s completion stall that reached about 77k pending attempts and 1 GB of worker memory. Finalizer admission is now bounded to max(worker capacity, 2 × completion batch size × completion shards). A finished handler keeps its worker slot while it waits, so the runtime stops claiming instead of growing; under the same stall it holds about 1,068 attempts, with memory 55 → 65 MB and no measurable throughput change. It also completes retried and metadata-carrying compact receipt claims by exact claim batch and item index.

Added on top:

  • Merge of release/0.6.6. The metadata-completion CTE keeps this PR's exact-index lookup in place of the job_ids GIN probe the branch gained in fix(queue-storage): index compact claim batches by job id (0.6) #684; the index still serves load_job, heartbeat, rescue and the other by-job lookups.
  • The finalizer wait prefers shutdown cancellation over a newly free permit, so no finalizer is spawned after shutdown gives up on draining.
  • Lifecycle hooks run under the finalizer bound. Each attempt's Started task is awaited inside its finalizer before the outcome hooks, and the slot is held until both return, so hooks slower than job throughput slow claiming instead of accumulating tasks that each hold the job (reproduced: 116k tasks and +1.78 GB in 10 s with a blocking hook, throughput unchanged). Maintenance's Rescued and duplicate Cancelled events stay detached so hooks cannot hold up rescue, capped at 1,024 outstanding with further events dropped and warned. test_queue_storage_slow_lifecycle_hook_holds_back_claiming fails without the change.
  • The stall test covers both completion paths: receipt claims and materialized leases (stalled by holding done_entries in SHARE mode). With the bound disabled both fail.

Review notes

  • The budget is per runtime, not per queue. Completion batching is one batcher per runtime sharded by job id, so flushes already mix queues, and memory is a per-process limit.
  • There is no fixed floor: 1,024 is the queue-storage default of 2 × 512 × 1. Deployments with large payloads can lower AWA_COMPLETION_BATCH_SIZE to shrink the bound in proportion.

Testing

Format and clippy clean; awa-worker unit tests, lifecycle_hook_test, and the stall, slow-hook, shutdown, metadata-completion and claim_batch_job_index integration tests pass on PG17.

JosiahBull and others added 5 commits November 8, 2026 10:10
Carry the complete fix from #648 onto the current 0.6 release branch, preserving heartbeat ownership and lock-contention retries. Add coverage for shutdown while finalizer capacity is saturated.

Co-authored-by: Brian Thorne <brian@hardbyte.nz>
…stic

Exercise the same batch writer from its private test module with explicit distinct microsecond run_at values. Preserve the 9,000-row insertion, segment-count and claim assertions without relying on host clock resolution.
…d-finalization-0.6

# Conflicts:
#	CHANGELOG.md
#	awa-model/src/queue_storage.rs
#	awa/tests/queue_storage_runtime_test.rs
A finished handler waiting for finalizer capacity could win a permit released after shutdown cancelled its wait, and spawn a finalizer that outlives shutdown. The wait now checks cancellation first.
The stall test now runs for both completion paths: receipt claims, stalled by the completion advisory locks, and materialized leases, stalled by holding done_entries in SHARE mode. With the finalizer bound disabled both fail.
@coderabbitai

coderabbitai Bot commented Nov 8, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 4fd661ef-5321-4fe6-b13e-08bae0a3d08a

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 8, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ✅ Completed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-08T17:39:07.863883Z eb6948f PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@coderabbitai

coderabbitai Bot commented Nov 8, 2026

Copy link
Copy Markdown

Add Carrot credits or activate Agent usage billing to use Autofix

Every attempt with lifecycle hooks spawned a detached task for Started, and its outcome hooks ran after the finalizer released its slot, so hooks slower than job throughput accumulated tasks each holding a copy of the job without slowing claiming. The Started task is now awaited inside the finalizer, before the outcome hooks, and the slot is held until both return. Maintenance's Rescued and duplicate Cancelled events stay detached so hooks cannot hold up rescue, but at most 1,024 are outstanding; further events are dropped with a warning.
@hardbyte
hardbyte merged commit a4c7fae into release/0.6.6 Nov 8, 2026
61 of 79 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

full-ci Run the full CI matrix (Python build+test, E2E) on this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants