Files
alkblobs/tasks/store-postgres-construction.md
T
glm-5.3-flash 67b927b13c feat(store): the postgres constructor wiring — the fleet-capable store shapes (wave 4)
- `KvEngine::Postgres` slotted in: all six kv-op dispatch arms, the
  `KvCursor::Postgres` materializing body behind `AnyCursor`'s kv arm
  (the recorded sub-enum design point, landed as predicted), and the
  engine-neutral `ensure_gc_schema` call creating `gc_pins` +
  `gc_window` in the fresh schema at construction (the fleet host's
  both-tables row, ADR-012 §5)
- The two named constructors behind feature `postgres` (default-off):
  `dual_tier_postgres_local(config, opts, root, threshold,
  window_delay)` — the fleet-capable-kv production shape — and
  `kv_only_postgres(config, opts, threshold, window_delay)`; the DSN
  connection settings + engine opts ride the constructor parameters,
  never invented defaults. `PgOpts` is pub and re-exported from
  `lib.rs` (it is on the public constructor signature now)
- The sweep's durable form runs on the postgres host: the form body
  extracted into `sweep_window_durable<W: EngineWindowState>` (sqlite's
  arm delegates, behavior unchanged), both SQL-backed arms keyed off
  the kv-engine enum, never a flag — wave 5's pg-lo dormancy slots in
  without reshaping
- Non-fleet posture recorded on both constructors (ADR-012 §3):
  implicitly `fleet: false`, the ADR-005 in-process protocol verbatim,
  the `fleet: true` declaration is wave 6 and slots in without
  reshaping
- Stale scope notes updated to the landed state (engine-representation
  doc, `KvCursor` design point, fleet-declaration paragraph,
  one-window-host paragraph, postgres module doc, gc.rs companion-seam
  note); the batch-delete helper's scope note stays (wave 6 consumer)
- 5 new env-driven construction tests (skipping server-less): the
  modes construct and introspect, both GC tables exist in the fresh
  schema, the window-delay default is the pinned 5-min constant and
  tunable (`0` legal), the kv-only rejection wiring is unchanged, the
  dual-tier shape round-trips through both tiers, and the durable
  form is observed staging/executing across sweeps on the postgres
  host

Verification: `cargo test` 69/19/3 ok; `cargo test --features postgres`
102/19/3 ok live (pglo-poc harness) and green server-less;
`cargo test --no-default-features --features postgres` (the pg-pure
build, ADR-013 §4) 75/2/3 ok server-less; `cargo test --all-features`
157/54/4 ok; clippy `-D warnings` green (default, postgres, pg-pure,
all-features); `cargo fmt --check` green; `cargo doc --no-deps` clean.
2026-10-12 06:34:36 +00:00

12 KiB

id, name, status, depends_on, scope, risk, impact, level, tags
id name status depends_on scope risk impact level tags
store-postgres-construction postgres constructor wiring — the fleet-capable store shapes completed
engine-postgres
engine-postgres-fleet
narrow low component implementation
wave-4
store
postgres
construction

Description

Slot postgres into the facade's engine representation — the slotting-in pattern src/store.rs's module doc pinned ("adding an enum variant and a named constructor is slotting in"):

  • KvEngine::Postgres variant behind #[cfg(feature = "postgres")] + the dispatch arms (put/get/has/size/ delete/list). The kv cursor dispatch slots the postgres materializing body into KvCursor (the recorded sub-enum design point: "postgres (wave 4) slots one arm in here" — the store.rs doc note is updated to the landed state).
  • Named constructors, feature-gated on postgres (default-off — they construct under --features postgres):
    • dual-tier kv = postgres + large = local — the fleet-capable-kv production shape (non-fleet here; see below); fallible (config parse, connect, schema bootstrap, the local root creation). Size-threshold dispatch at the constructor-tunable threshold as in the sqlite shape.
    • kv-only(postgres) — no large tier; threshold is the put-time rejection point (ADR-012 §6.2; the rejection machinery is the put seam's, already landed — only the constructor slots in).
    • Both take the connection settings + engine opts (recorded design point: the DSN form — the tokio-postgres Config-parseable string, the alkstore open(config, PgOpts) pin adapted to the named-constructor shape — and the opts shape carrying schema name, pool size, synchronous_commit; engine-configuration concerns ride the constructor parameters, never invented defaults) and the delete-window delay parameter (Duration, default DEFAULT_DELETE_WINDOW_DELAY, 0 the legal degenerate tuning — the sqlite constructors' signature shape).
  • Non-fleet posture — these constructors are implicitly fleet: false (ADR-012 §3): the ADR-005 in-process protocol applies verbatim regardless of engine; pins are in-process guards, the sweep lease is the in-process lock, and none of the EngineFleetState clauses run. The fleet: true declaration is wave 6 (the fleet-validity predicate + constructor declarations) — no fleet parameter is added here; wave 6 slots it in without reshaping. Recorded in the constructor docs so the wave-6 slotting is a non-event.
  • ensure_gc_schema at construction — the store-core call (engine-neutral; the postgres arm creates gc_pins + gc_window per the fleet host's applicability row). A construction failure is Err(Error::Io) per the fallible-constructor pattern.
  • The one-window-host rule's store-core posture — already recorded (the durable window hosts on the kv engine when it is SQL-backed); the postgres arm slots in under it with no reshaping. Verify the recorded posture's wording covers postgres (it names "sqlite or postgres" already — ADR-012 §5) and that the form branch keys off the kv-engine enum, never a flag.
  • Stale scope notes updated — the engine-representation doc's "postgres (wave 4)" forward references, the KvCursor design-point note, and any #![allow(dead_code)] scope notes whose scope changes (the batch-delete helper's note stays — its consumer is still wave 6).
  • Constructor unit tests: the modes construct and introspect correctly (mode()/threshold()), ensure_gc_schema ran (both GC tables exist in the fresh schema), the window-delay default is the pinned constant, kv-only rejection wiring unchanged, the dual-tier shape round-trips end-to-end (a smoke put/get through both tiers). Env-driven, skipping cleanly server-less (the engine tests' convention).
  • The pg-pure build — cargo check --no-default-features --features postgres (and the tests target under it): ADR-013 §4's supported non-default configuration first becomes constructible here; verify it compiles clean.

Acceptance Criteria

  • KvEngine::Postgres slots in; all six kv ops dispatch; the kv cursor body slots into KvCursor (the design-point note updated to the landed state)
  • dual_tier_postgres_local + kv_only_postgres constructors exist behind feature postgres, take connection settings + engine opts + threshold + window delay, fallible where I/O is fallible
  • ensure_gc_schema runs at construction (both GC tables in the fresh schema); the window-delay shipped default is 5 min (pinned constant) and constructor-tunable; 0 legal
  • The non-fleet posture recorded (in-process protocol verbatim; the fleet: true declaration is wave 6, slotting in without reshaping)
  • The one-window-host posture verified to cover postgres; the form branch keys off the kv-engine enum
  • The pg-pure build (--no-default-features --features postgres) compiles clean
  • cargo test (default) green; cargo test --features postgres green server-less (skipping); cargo clippy --all-targets -- -D warnings and cargo fmt --check green (default + --features postgres)

References

  • src/store.rs (the engine-representation design point; the constructor modes; the slotting-in pattern; the KvCursor sub-enum design point)
  • docs/architecture/decisions/011-vocabulary-tiers-engines-and-fleet-state.md §4 (modes; the constructor table)
  • docs/architecture/decisions/012-pre-decomposition-consistency-rulings.md §3 (fleet activation is a declaration — wave 6), §5 (the one-window-host rule), §6.3 (dual-tier shapes)
  • docs/architecture/decisions/008-trait-size-probe-fleet-gc-and-large-engines.md §2 (the window delay, default 5 min)
  • docs/architecture/decisions/013-family-composition-reactive-boundary-and-feature-graph.md §4 (the feature graph; the pg-pure build)
  • tasks/engine-postgres.md, tasks/engine-postgres-fleet.md (the engine
    • seam bodies this wires)
  • tasks/store-sqlite-construction.md (the structural twin's recorded design points)

Notes

Implemented in src/store.rs + src/postgres.rs + src/lib.rs (wave 4, following store-sqlite-construction — the structural twin — point for point). Recorded design points, as resolved:

  • Opts on the public surface — PgOpts went pub (and is re-exported from lib.rs behind the feature gate): the constructors' engine-opts parameter is on the public constructor signature, so the type must be nameable there (the alkstore open(config, PgOpts) pin adapted to the named-constructor shape; the connection settings remain the separate DSN-string argument).
  • KvCursor slotting — postgres's materializing body slotted into the recorded sub-enum exactly as predicted: one variant, two ReadCursor impl arms, no reshaping of AnyCursor/Blob. The store.rs design-point note reads landed.
  • ensure_gc_schema rides the engine-neutral KvEngine call — the postgres arm forwards to the EngineWindowState clause (the fleet host's both-tables body: gc_pins + gc_window in the fresh schema), and both constructors dispatch through it (the store core calls the kv engine, never a typed postgres path). Construction failure is Err(Error::Io) per the fallible- constructor pattern (? throughout).
  • The sweep's form branch — the durable-form body was extracted into sweep_window_durable<W: EngineWindowState> (behavior unchanged for sqlite, whose arm now delegates); both SQL-backed arms call it, so the form branch still keys off the kv-engine enum, never a flag, and wave 5's pg-lo dormancy slots in without reshaping. The one-window-host posture's wording now names both SQL-backed hosts (module doc + the sweep doc).
  • Non-fleet posture — both constructors' docs carry the ADR-012 §3 recording verbatim: implicitly fleet: false, the ADR-005 in-process protocol applies regardless of engine (in- process pins, in-process sweep lease, no EngineFleetState clause runs), and the fleet: true declaration is wave 6, slotting in without reshaping — no fleet parameter carried.
  • Signature shape — dual_tier_postgres_local(config, opts, root, threshold, window_delay) / kv_only_postgres(config, opts, threshold, window_delay): connection settings first (the tokio-postgres Config-parseable DSN string), engine opts second, then the sqlite twins' remaining parameters (root/threshold/ window delay). The DSN is &str — PostgresBackend::new parses; no invented defaults anywhere.
  • Clippy notes — KvEngine needed a scoped #[allow(clippy::large_enum_variant)] under the postgres configs (the payloads are structurally dissimilar — one Arc vs the pooled-connection posture inline — and all dispatch rides the enum by reference, so the size difference costs nothing; recorded on the enum doc). The store-construction table_exists probe (pg_tables, schema-scoped) mirrors the sqlite engine's #[cfg(test)] instrument.
  • Tests (5 new, env-driven, skipping server-less) — dual-tier construction + routing + both-GC-tables schema check; kv-only construction + rejection wiring (immediate, overflow, zero residue, at-threshold lands); the window-delay default/tunings/ zero; the dual-tier round-trip through both tiers with tier- placement assertions; and a durable-form sweep smoke (zero-delay: first sweep stages and executes nothing — the inline form would delete in-sweep, so this is the form-branch-is-postgres proof — the second sweep executes the overdue set re-arbitrated at execution time). The test-side KvEngine matches in the existing test modules gained Postgres arms for --all-features exhaustiveness.
  • Stale scope notes updated to the landed state: the engine- representation doc, the KvCursor design point, the fleet- declaration paragraph, the one-window-host paragraph, the postgres module doc's forward reference — and gc.rs's companion-seam note (the fleet family now "waits for wave 6", its clause bodies landed with wave 4). The batch-delete helper's scope note stays (its consumer is still wave 6).

Summary

Completed 2026-10-12 (wave 4). Postgres slotted into the facade: KvEngine::Postgres with all six kv-op dispatch arms, the KvCursor::Postgres materializing body, the ensure_gc_schema engine-neutral call creating gc_pins + gc_window in the fresh schema at construction, and the two named feature-gated constructors (dual_tier_postgres_local, kv_only_postgres) taking the DSN connection settings + PgOpts (now public and re-exported) + threshold + the constructor-tunable delete-window delay (DEFAULT_DELETE_WINDOW_DELAY pinned at 5 min, 0 legal) — both implicitly non-fleet per ADR-012 §3 with wave 6's declaration recorded as a non-reshaping slotting. The sweep's durable form runs on the postgres host through the kv-engine-enum-keyed branch (sweep_window_durable, shared with sqlite's arm). Verification: cargo test 69/19/3 ok (default), cargo test --features postgres 102/19/3 ok live and green server-less, cargo test --no-default-features --features postgres (the pg-pure build, ADR- 013 §4's first constructible configuration) 75/2/3 ok server-less, cargo test --all-features 157/54/4 ok, clippy -D warnings green on default + postgres + pg-pure + all-features, cargo fmt --check green, cargo doc --no-deps clean.