feat(engines): the postgres kv engine — the fleet host's first engine (wave 4)

The 'postgres' kv-tier engine (ADR-007, feature 'postgres', default-off)
against the wave-1 trait: the sqlite engine's structural twin on a
Pooled-Postgres driver cluster.

- One engine-owned schema (default 'alkblobs'; quoted-identifier
  boundary via the alkstore quote_identifier pattern) holding the B5
  row shape — key bytea PK / value bytea NOT NULL / size bigint NOT
  NULL, WITH (fillfactor = 90) — idempotently bootstrapped at
  construction; autovacuum and the ~40x small-tier storage overhead
  recorded as posture, not silence
- deadpool pool with DEFAULT_MAX_SIZE = 8 (load-bearing, POC #5 B2);
  per-connection prepare_cached discipline (B5: statements die with
  sessions); the synchronous_commit parity knob as connect options on
  every pooled connection (default 'on', configurable, alkstore
  src/opts.rs mechanics)
- CAS first-writer-wins (INSERT ... ON CONFLICT DO NOTHING) on both
  put forms; metadata-only size probe riding the PK index (EXPLAIN
  gate-tested); EXISTS has; materializing get cursor; degenerate
  in-memory stage with both hygiene forms (fail_commit injection)
- list: the single-statement MVCC-snapshot cursor (portal-batched row
  stream, keys only); crate-internal batch-delete helper
  (DELETE ... WHERE key = ANY() over bytea[]), scope-noted until
  wave 6; virgin-store read-only split via SQLSTATE 42P01 mapping
- 15 in-module unit tests, env-driven (ALKBLOBS_PG_*), skipping
  cleanly server-less; green against the dockerized pglo-poc harness
  server (:15432)

Verified: cargo test; cargo test --features postgres (84 lib tests);
cargo test --all-features (139); clippy all-targets, default +
features + all-features, -D warnings; fmt --check; doc --no-deps.
This commit is contained in:
glm-5.3-flash committed 2026-10-12 06:02:24 +00:00
1 parent 7ea6dd6bcb
commit 1efc46f953
2 files changed
+1360 -5

No files matched your search

+1291 -2
View File
File diff suppressed because it is too large. Load diff
+69 -3
View File
@@ -1,7 +1,7 @@
--- ---
id: engine-postgres id: engine-postgres
name: postgres kv engine — the fleet-capable engine name: postgres kv engine — the fleet-capable engine
status: pending status: completed
depends_on: [] depends_on: []
scope: narrow scope: narrow
risk: medium risk: medium
@@ -174,8 +174,74 @@ the engine and its in-module unit tests only.
## Notes ## Notes
> To be filled by implementation agent > Implemented in `src/postgres.rs` (wave 4, this task's only code
> change; `src/lib.rs`'s `#[cfg(feature = "postgres")] pub mod
> postgres;` gate pre-existed). Recorded design points, as resolved:
>
> - **Opts shape** — a crate-internal `PgOpts` (`schema` /
> `max_size` / `synchronous_commit`), mirroring alkstore's
> `src/opts.rs`; the constructor takes the tokio-postgres
> `Config`-parseable connection string first, `PgOpts` second.
> `max_size = 0` fails at entry, before any round trip; an empty
> schema string selects the default.
> - **Schema name** — default `"alkblobs"`; every statement composes
> the table through `quote_identifier` (the alkstore boundary), so a
> hostile schema name (embedded `"`, reserved-word-shaped) is tested
> green. `size`/`value`/`key` are quoted in DDL per the alkstore
> hazard list, plain in DML (`key`, `value`, `size` non-reserved).
> - **Pool default** — `DEFAULT_MAX_SIZE = 8`, `RecyclingMethod::Fast`
> (alkstore precedent); deadpool-postgres 0.14 / tokio-postgres 0.7.
> - **list fetch shape** — single `SELECT key … ORDER BY key` through
> the deadpool client: one statement = one MVCC snapshot
> (vacuum-ghost-stable); tokio-postgres's row stream drains the
> server-side portal in bounded batches and the collection
> materializes only the key column. Ordering by key is engine-local
> (the trait leaves ordering unspecified).
> - **Virgin-store discriminant** — SQLSTATE 42P01
> (`is_undefined_table`), mapped on reads (absent/empty), delete
> (`Missing`), and `delete_batch` (`Ok(0)`); writes and staged
> commits surface `Error::Io`. The schema-less fixture connects via
> a `#[cfg(test)] new_schemaless` constructor (the sqlite
> `new_tableless` pattern) against a schema that was never
> bootstrapped.
> - **Stage hygiene mechanics** — the staged buffer is
> `std::mem::take`n before the pool checkout, so a failed commit
> (injection or engine error) strands no staged bytes; the
> `#[cfg(test)] fail_commit` knob mirrors sqlite/mem.
> - **No new dependencies** — `postgres = ["dep:tokio-postgres",
> "dep:deadpool-postgres"]` was already in `Cargo.toml`; `list` uses
> the client's collected query (row-stream under the hood) rather
> than pulling futures-util for `query_raw`.
> - **Test harness quirks** — `simple_query("SHOW …")` returns
> `SimpleQueryMessage`s (skip to the `Row` variant); `size`'s
> EXPLAIN plan gate embeds the key as a `'\x…'` literal (PREPARE
> cannot wrap EXPLAIN) and asserts `Index Scan` + `blobs_pkey`.
> - Isolation convention: one fresh schema per test
> (`abt_{tag}_{pid}_{seq}`), the alkstore suite-factory pattern, on
> the shared harness database.
## Summary ## Summary
> To be filled on completion > Completed 2026-10-12 (wave 4). `src/postgres.rs` implements the
> seven-method `Backend` + `put_staged` behind feature `postgres`
> (default-off) — deadpool pool (default 8, load-bearing posture
> recorded), per-connection `prepare_cached` discipline, the
> `synchronous_commit` parity knob wired as connect options on every
> pooled connection (default `on`, configurable), one engine-owned
> schema (`alkblobs`, quoted-identifier boundary) holding the B5 row
> shape with `fillfactor = 90` idempotently bootstrapped at
> construction, CAS first-writer-wins via `ON CONFLICT DO NOTHING` on
> both put forms, the metadata-only `size` probe (PK-index-tested via
> EXPLAIN), the degenerate in-memory stage with both hygiene forms, the
> single-MVCC-snapshot `list` cursor, and the crate-internal
> `delete_batch` (`key = ANY($1)` over `bytea[]`, scope-noted until
> wave 6). Natively async — no spawn_blocking. 15 in-module unit tests,
> env-driven (`ALKBLOBS_PG_HOST/PORT/USER/PASSWORD/DB`), skipping
> cleanly server-less; all green against the dockerized pglo-poc
> harness server (:15432). Verified: `cargo test` (69/19/3 ok),
> `cargo test --features postgres` (84/19/3 ok, server live), `cargo
> test --all-features` (139/54/4 ok), `cargo clippy --all-targets` and
> `--all-features --all-targets -- -D warnings` green, `cargo fmt
> --check` green, `cargo doc --no-deps` clean. Engine-state clause
> families remain `engine-postgres-fleet`; constructor wiring remains
> `store-postgres-construction`.