Skip to content

feat: expose public Postgres adapter API#259

Merged
hardbyte merged 1 commit into
mainfrom
feat/public-adapter-api
May 15, 2026
Merged

feat: expose public Postgres adapter API#259
hardbyte merged 1 commit into
mainfrom
feat/public-adapter-api

Conversation

@hardbyte

@hardbyte hardbyte commented May 14, 2026

Copy link
Copy Markdown
Owner

Summary

Expose a stable public Postgres insert-preparation contract for external Rust enqueue adapters.

  • add awa::adapter::postgres / awa_model::adapter::postgres
  • add PreparedJobInsert, prepare_job_insert, prepare_raw_job_insert
  • expose canonical single-row INSERT_JOB_SQL and UNIQUE_VIOLATION_SQLSTATE
  • switch the built-in tokio-postgres bridge to use the public contract
  • update bridge docs and ADRs 001/016/017 plus the ADR index

Why

The SeaORM adapter review showed that exposing only a pool helper is not enough for real transactional enqueue. External Rust adapters need to execute the Awa insert through their own driver or transaction type, while still reusing Awa's validation, state selection, uniqueness, and ordering-key logic.

This API keeps Awa Postgres-only and avoids a premature generic adapter trait. Awa owns insert preparation and the SQL contract; adapter crates own driver-specific execution and row decoding.

Self-review

  • Checked that PreparedJobInsert has private fields and read-only getters, so callers cannot construct semantically invalid prepared inserts.
  • Verified the public SQL uses driver-friendly casts for state, priority, max_attempts, tags, and unique_states.
  • Confirmed the existing tokio-postgres bridge now consumes the same public API external crates should use.
  • Updated ADR-016 because it previously said PreparedRow was private and future adapters required in-crate modules.
  • Updated ADR-001 to clarify that "no pluggable adapter layer" means no storage backend abstraction, not no Postgres enqueue adapters.
  • Updated ADR-017 to cross-link the same insert-only bridge principle for Python and Rust.
  • Remaining design caveat: row decoding remains adapter-specific. That is intentional until there is a clearly useful common row API across Rust drivers.

Validation

cargo fmt --all --check
cargo test -p awa-model --lib insert::tests
cargo check -p awa-model --features tokio-postgres
cargo check -p awa
cargo clippy -p awa-model --features tokio-postgres --all-targets -- -D warnings
DATABASE_URL=... cargo test -p awa-model --features tokio-postgres --test bridge_tokio_pg_test
DATABASE_URL=... cargo test -p awa --test validation_test t06_transactional_atomicity_rust -- --nocapture

Summary by CodeRabbit

  • New Features

    • Introduced a stable public adapter API for external Rust Postgres integrations to enqueue jobs independently of sqlx
    • Added canonical preparation interface and SQL contract for job insertion
  • Documentation

    • Added comprehensive guide on using the Rust Postgres adapter API for external integrations
    • Updated architecture documentation with new adapter contract specifications
  • Bug Fixes

    • Added safeguard in SQL migration to prevent errors when expected database columns are absent
  • Tests

    • Added integration tests validating the public adapter API

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 14, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@hardbyte has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 29 minutes and 27 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f8cd78b6-9c28-47e9-8be2-d31f7f1688f5

📥 Commits

Reviewing files that changed from the base of the PR and between f375d51 and 66dc761.

📒 Files selected for processing (16)
  • README.md
  • awa-model/README.md
  • awa-model/migrations/v013_storage_auto_finalize.sql
  • awa-model/src/adapter.rs
  • awa-model/src/bridge.rs
  • awa-model/src/insert.rs
  • awa-model/src/job.rs
  • awa-model/src/lib.rs
  • awa/src/lib.rs
  • awa/tests/adapter_api_test.rs
  • awa/tests/queue_storage_runtime_test.rs
  • docs/adr/016-bridge-adapters.md
  • docs/adr/016-rust-postgres-enqueue-adapter-api.md
  • docs/adr/017-python-transaction-bridging.md
  • docs/adr/README.md
  • docs/bridge-adapters.md
📝 Walkthrough

Walkthrough

This PR introduces a stable, insert-focused public Rust API for external Postgres job enqueue adapters. It adds shared job preparation functions (prepare_job_insert, prepare_raw_job_insert), a PreparedJobInsert struct with ordered accessor methods, canonical INSERT SQL with explicit casts, and integration tests. The tokio-postgres bridge is refactored to use the new shared preparation. A SQL migration guard and comprehensive documentation (new ADR-016) define the contract and scope.

Changes

Public Rust Postgres Enqueue Adapter API

Layer / File(s) Summary
JobState canonical string representation
awa-model/src/job.rs
JobState::as_str() is added as a const fn returning the canonical snake_case string for each state variant. Display impl now uses this single source of truth instead of repeating a match statement.
Prepared insert structure and driver SQL
awa-model/src/insert.rs
PreparedJobInsert struct introduced with ordered accessor methods (kind, queue, args, state_db_str, priority, max_attempts, run_at, metadata, tags, unique_key, unique_states_bit_string, ordering_key). New POSTGRES_INSERT_JOB_SQL constant with explicit casts and state::text column for driver compatibility.
Public preparation entry points
awa-model/src/insert.rs, awa-model/tests/*
prepare_job_insert (typed) and prepare_raw_job_insert (raw kind/JSON) become the stable public preparation API. Internal prepare_row* helpers delegate to these functions. COPY "unique" insertion path switches to POSTGRES_INSERT_JOB_SQL. Unit tests validate canonical bind values and SQL patterns.
Adapter module and public constants
awa-model/src/adapter.rs
New adapter.rs module with public postgres submodule re-exporting prepare_job_insert, prepare_raw_job_insert, PreparedJobInsert, and defining INSERT_JOB_SQL and UNIQUE_VIOLATION_SQLSTATE ("23505") constants.
Bridge adapter refactoring to shared preparation
awa-model/src/bridge.rs
tokio-postgres bridge updated to use prepare_job_insert/prepare_raw_job_insert instead of prepare_row, to accept PreparedJobInsert in execution, and to use INSERT_JOB_SQL and state_db_str() from the prepared job. Imports and execution wiring are updated.
Public API surface and re-exports
awa-model/src/lib.rs, awa/src/lib.rs
adapter module and prepare_job_insert, prepare_raw_job_insert, PreparedJobInsert are added to public re-exports at crate root for ergonomic access.
Integration tests and adapters
awa/tests/adapter_api_test.rs
Test scaffolding for database setup/migrations, cleanup helpers, and execute_adapter_insert helper that binds PreparedJobInsert fields to INSERT_JOB_SQL. Tests validate canonical bind values, end-to-end insertion, and transaction rollback semantics.
SQL migration safety guard
awa-model/migrations/v013_storage_auto_finalize.sql
Migration adds an EXISTS check on information_schema.columns before updating queue_lanes.available_count, preventing errors when the column is absent in the target schema.
ADR and user documentation
docs/adr/016-rust-postgres-enqueue-adapter-api.md, docs/adr/017-python-transaction-bridging.md, docs/bridge-adapters.md, README.md, awa-model/README.md, docs/adr/README.md
New ADR-016 defines shared insert-preparation strategy and stable public API contract. ADR-017 clarifies alignment with Python bridge semantics. New bridge-adapters.md section documents Rust external adapter API with usage patterns and constraints. README files updated to reference the new ADR and feature.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • hardbyte/awa#181: Introduces the shared Postgres "compat" insert surface (awa.insert_job_compat) that this PR's stable adapter API targets and validates against.
  • hardbyte/awa#178: Updates the tokio-postgres adapter's enqueue path, which this PR refactors to use the new shared job-preparation contract.

Poem

A rabbit bounds with joy so keen,
External bridges, safe and clean!
With shared prepare and ordered bind,
No drift in schemas left behind. 🐰✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and concisely describes the main change: exposing a public Postgres adapter API. This matches the core objective of introducing stable external adapter building blocks.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/public-adapter-api

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

Comment @coderabbitai help to get the list of available commands and usage tips.

@hardbyte hardbyte force-pushed the feat/public-adapter-api branch 4 times, most recently from ef352ea to f375d51 Compare May 14, 2026 20:18
@hardbyte hardbyte marked this pull request as ready for review May 14, 2026 20:18

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/adr/016-rust-postgres-enqueue-adapter-api.md`:
- Line 38: The ADR/documentation refers to the accessor as `state_str` but the
canonical public bind accessor is `state_db_str()`; update the text and any code
examples in this document to consistently use `state_db_str()` (including
references around portable enum decoding and any sample calls or bindings), and
verify mentions of the accessor in related sections or examples match the
`state_db_str()` function name to prevent adapter implementation errors.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8b6214bb-aa89-4e3d-954c-bf4179bf56ae

📥 Commits

Reviewing files that changed from the base of the PR and between c87f424 and f375d51.

📒 Files selected for processing (15)
  • README.md
  • awa-model/README.md
  • awa-model/migrations/v013_storage_auto_finalize.sql
  • awa-model/src/adapter.rs
  • awa-model/src/bridge.rs
  • awa-model/src/insert.rs
  • awa-model/src/job.rs
  • awa-model/src/lib.rs
  • awa/src/lib.rs
  • awa/tests/adapter_api_test.rs
  • docs/adr/016-bridge-adapters.md
  • docs/adr/016-rust-postgres-enqueue-adapter-api.md
  • docs/adr/017-python-transaction-bridging.md
  • docs/adr/README.md
  • docs/bridge-adapters.md
💤 Files with no reviewable changes (1)
  • docs/adr/016-bridge-adapters.md

The native sqlx path is not required to use this driver-friendly SQL. It may
keep a typed `PgExecutor` query that binds `JobState` directly and returns
`SELECT *`, while external adapters use `INSERT_JOB_SQL` with text casts and
`state_str` for portable enum decoding.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Use the canonical accessor name consistently (state_db_str).

Line 38 says state_str, but the documented/public bind accessor is state_db_str(). Please align this term to avoid adapter implementation errors.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/adr/016-rust-postgres-enqueue-adapter-api.md` at line 38, The
ADR/documentation refers to the accessor as `state_str` but the canonical public
bind accessor is `state_db_str()`; update the text and any code examples in this
document to consistently use `state_db_str()` (including references around
portable enum decoding and any sample calls or bindings), and verify mentions of
the accessor in related sections or examples match the `state_db_str()` function
name to prevent adapter implementation errors.

@hardbyte hardbyte force-pushed the feat/public-adapter-api branch from b769de8 to 66dc761 Compare May 14, 2026 20:49
@hardbyte hardbyte merged commit 7660fde into main May 15, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant