feat(gc): the postgres engine-state clause families — the fleet host's full seam (wave 4)
- EngineWindowState: the both-tables ensure_gc_schema (gc_pins with the (key, owner) identity + gc_window), idempotent window_stage (the upsert discipline per (key, deadline)), and window_take as one atomic DELETE ... RETURNING with the <= boundary - EngineFleetState: PgJointTx (the pooled checkout carrying a session-level BEGIN), joint_put (the CAS clause inside the held tx), pin_commit (pin-row upsert-renewals + commit, rollback-on-failure => zero residue), pin_renew (expiry = now + DEFAULT_PIN_TTL, never resurrects), pin_check (the two-variant classification), arbitrate (the FOR UPDATE finger-lock folding pins + registered liveness-table references), and the engine-side register_liveness_source home - The sweep lease: the session-scoped pg advisory lock with the namespaced FNV lock key and the same-connection acquire/release holding discipline (the lease's checkout stored until release) - 13 contract tests (28 postgres tests total), env-driven, skipping cleanly server-less; verified green against the live pglo-poc harness server; clippy/fmt green default + --features postgres Verification: cargo test (69/19/3 ok), cargo test --features postgres server-less (97 ok, 28 skips) and live (97 ok), cargo test --all-features (152/54/4 ok), cargo clippy -D warnings (both configs), cargo fmt --check, cargo doc --no-deps.
This commit is contained in:
1 parent
1efc46f953
commit
29209fe53f
2 files changed
+1492
-11
No files matched your search
+1398
-8
File diff suppressed because it is too large.
Load diff
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: engine-postgres-fleet
|
||||
name: postgres engine-state clause families — the fleet host's full seam
|
||||
status: pending
|
||||
status: completed
|
||||
depends_on: [engine-postgres]
|
||||
scope: moderate
|
||||
risk: medium
|
||||
@@ -191,8 +191,99 @@ engine-level contract tests.
|
||||
|
||||
## Notes
|
||||
|
||||
> To be filled by implementation agent
|
||||
> Implemented in `src/postgres.rs` (wave 4, this task's only code
|
||||
> change; both impls sit behind the pre-existing `#[cfg(feature =
|
||||
> "postgres")]` module gate). Named design points, as resolved:
|
||||
>
|
||||
> - **`JointTx`** — a crate-internal `PgJointTx`: the deadpool checkout
|
||||
> (`deadpool_postgres::Object`) held for the tx's life, with the
|
||||
> transaction opened as an explicit session-level `BEGIN` and closed
|
||||
> by `COMMIT`/`ROLLBACK` in the clause bodies. tokio-postgres's
|
||||
> `Transaction` borrows its client (`&mut`), so it cannot be
|
||||
> co-owned with the checkout behind one `Send` field; the exclusive
|
||||
> checkout *is* what "the pooled client carries the tx" means
|
||||
> (nothing else can interleave on the session), and ownership stays
|
||||
> with the store core from `begin_joint_tx` to `pin_commit` per the
|
||||
> trait's pinned ruling. Every `pin_commit` failure path rolls the
|
||||
> tx back before surfacing `Err` (zero residue); dropping a tx
|
||||
> mid-flight is outside the seam contract (the store core holds it).
|
||||
> - **`pin_renew` successor time** — the engine computes
|
||||
> `expiry = now + DEFAULT_PIN_TTL` from the shipped 60 s constant
|
||||
> (`DEFAULT_PIN_TTL_SECS`, a backend field, constructor-tunable when
|
||||
> wave 6's fleet constructor lands); the store owns the TTL and the
|
||||
> TTL/3 cadence (`pin_commit`'s rows carry the store-resolved
|
||||
> expiry). The update's predicate requires un-expired rows only, so
|
||||
> expired/absent rows are never resurrected.
|
||||
> - **Timestamp encoding** — signed i64 nanos from the Unix epoch,
|
||||
> `time_to_nanos`/`nanos_to_time` mirrored as per-engine bodies (the
|
||||
> sqlite helpers are reference, one encoding).
|
||||
> - **Sweep lease** — session-scoped pg advisory lock
|
||||
> (`pg_try_advisory_lock`/`pg_advisory_unlock`): the only scope whose
|
||||
> holdership ends at owner death/session loss (ADR-013 §2). Lock key
|
||||
> = FNV-1a over `alkblobs:sweep:{schema}` folded to positive i64 —
|
||||
> the fleet's shared schema is one lock domain (one sweeper per
|
||||
> pool), co-tenant schemas derive distinct keys. **Connection
|
||||
> holding**: the acquired checkout is stored under a
|
||||
> `parking_lot::Mutex<Option<Object>>` until release, so
|
||||
> acquire/release ride the same session (the recorded pitfall);
|
||||
> a second acquire answers `Ok(false)` from the mutex before any
|
||||
> pool checkout; release is no-op-safe and never errors (an unlock
|
||||
> failure is the session-loss reaping case itself).
|
||||
> - **Pin rows** — `gc_pins` carries `PRIMARY KEY (key, owner)` (the
|
||||
> row identity) and `pin_commit` inserts with `ON CONFLICT (key,
|
||||
> owner) DO UPDATE SET expiry`: a re-put by the same instance
|
||||
> upsert-renews its row (ADR-010 §4), protection composes by row.
|
||||
> - **`arbitrate`** — one `BEGIN … COMMIT` fold: un-expired pin rows
|
||||
> first, then each registered liveness-table reference, all
|
||||
> `SELECT … FOR UPDATE LIMIT 1` keyed at delete time, one bool
|
||||
> answer. The registration list (a `parking_lot::Mutex<Vec<String>>`
|
||||
> behind an `Arc`, shared with clones) is snapshotted before the
|
||||
> server round trip.
|
||||
> - **Liveness-table registration** —
|
||||
> `PostgresBackend::register_liveness_source(ref)` is the engine-side
|
||||
> home of ADR-012 §6.6's fleet registration: every dot-component of
|
||||
> the reference rides `quote_identifier` at registration (hostile
|
||||
> names safe, malformed refs error), re-registration is idempotent,
|
||||
> the engine holds references only and never creates the tables.
|
||||
> - **Virgin tolerance asymmetry** — `window_take` maps SQLSTATE 42P01
|
||||
> to empty (the sqlite twin's read parity); the fleet clauses carry
|
||||
> no tolerance — they run in fleet mode where store construction has
|
||||
> ensured the GC schema.
|
||||
> - **Error mapping** — new `pg_err` for the clause bodies surfaces
|
||||
> the `DbError` message + SQLSTATE (plain `Display` is just "db
|
||||
> error"); the landed engine's sites keep the original mapping.
|
||||
> - **Contract tests (13 new; 28 postgres tests total)** — the
|
||||
> both-tables schema + the never-created embedder column probe,
|
||||
> stage idempotence/re-stage, take's exact set / atomic re-take /
|
||||
> future rows / `<=` boundary / pre-epoch encoding / virgin shapes,
|
||||
> the joint publish-together path with CAS dedup + upsert renewal,
|
||||
> the injected joint-failure zero-residue abort, `pin_renew`'s
|
||||
> live/expired/absent trio, `pin_check`'s two variants, arbitrate
|
||||
> folding pins + a test-owned embedder table plus the live
|
||||
> finger-lock-blocks-concurrent-renewal proof, and the advisory
|
||||
> lock's acquire/contention/release + foreign-session-loss reaping.
|
||||
> Harness server verified live 2026-10-12.
|
||||
|
||||
## Summary
|
||||
|
||||
> To be filled on completion
|
||||
> Completed 2026-10-12 (wave 4). `src/postgres.rs` implements
|
||||
> `EngineWindowState` (the fleet host's both-tables `ensure_gc_schema`,
|
||||
> idempotent `window_stage`, atomic `DELETE … RETURNING`
|
||||
> `window_take` with the `<=` boundary) and `EngineFleetState`
|
||||
> (PgJointTx joint entry+pin tx, `pin_commit` with rollback-on-failure
|
||||
> and upsert-renewal pin-row inserts, `pin_renew`'s no-resurrection
|
||||
> expiry semantics, two-variant `pin_check`, the `FOR UPDATE`
|
||||
> finger-lock `arbitrate` folding pin rows + registered liveness-table
|
||||
> references, and the session-scoped advisory sweep lease with its
|
||||
> same-connection holding discipline) — every clause family of
|
||||
> ADR-012 §5's postgres row, contract-tested in-module with the
|
||||
> established env-driven harness convention (skip cleanly server-less,
|
||||
> green against the live pglo-poc server). 13 new tests; fleet
|
||||
> activation remains wave 6 (the store core never calls the fleet
|
||||
> clauses under `fleet: false`), and the `ensure_gc_schema`
|
||||
> constructor wiring remains `store-postgres-construction`. Verified:
|
||||
> `cargo test` (69/19/3 ok), `cargo test --features postgres`
|
||||
> server-less (97 ok, 28 skips; with server 97 ok, all live),
|
||||
> `cargo test --all-features` (152/54/4 ok), `cargo clippy
|
||||
> --all-targets -- -D warnings` and `--all-features --all-targets`
|
||||
> green, `cargo fmt --check` green, `cargo doc --no-deps` clean.
|
||||
Reference in new issue
Block a user