Files
alkstore/tasks/pg-fix-open-path.md
T

3.4 KiB


id: pg-fix-open-path name: Fix max_size: 0 open hang + DSN options override (review 002 Finding 3 + options note) status: pending depends_on: [] scope: single risk: low impact: component level: implementation tags: [wave-4-fixes, postgres-engine, open]

Description

Two open-path fixes in alkstore-postgres/src/store.rs (open_store), from the wave-4 general review:

Finding 3 (MEDIUM, live-proven): PgOpts { max_size: 0 } hangs open forever. Site: store.rs:162-165 + the bootstrap pool.get() at store.rs:177 — deadpool (0.13/0.14) does not validate max_size and defaults to no timeouts, so a max_size: 0 pool can never grant a checkout: open blocks forever at the bootstrap checkout (no BuildError, no default pool timeouts) instead of failing typed. Probe (removed): open with max_size: 0 timed out at 5 s, never returned.

Fix shape (the review's): validate max_size > 0 in open_store — typed Error::Database before any round trip (the engine-wide validate-at-entry posture; the source-chain detail should say what was rejected, e.g. "max_size must be positive"). The alternative shape (configure deadpool timeouts so the hang surfaces as an error) is weaker — a timeout-configured hang still burns the consumer's time; prefer the guard. Do both only if trivial.

Minor note (same file, same surface): store.rs:152-156 — pool_cfg.options(...) replaces any options= present in the consumer's DSN (tokio-postgres's setter semantics) — a silent config override. Preferred fix: append to the DSN's existing options string (tokio-postgres Config::get_options() reads what the parse carried) so the engine's synchronous_commit SET rides alongside whatever the consumer configured. If appending proves impractical, document at the site and in the crate docs that engine-configured options win — but append is the honest default (the consumer's DSN options were there first).

Tests (against the harness server): max_size: 0 fails typed and promptly (assert the error; the test's own structure bounds the hang — a regression re-hangs and fails the test by timeout); a DSN carrying pre-existing options= plus open succeeds and synchronous_commit is still observable via SHOW on both settings (the append path doesn't break the engine's SET); the existing opts-flow tests stay green.

Acceptance Criteria

  • max_size: 0 fails open with a typed Database error before any round trip — pinned by test (prompt failure, no hang)
  • The consumer DSN's options= survive: appended, not replaced — pinned by test (DSN with options + engine SET coexist, SHOW observable)
  • If append proved impractical instead: the engine-wins semantics documented at the site and in crate docs (record the decision in Notes)
  • Existing open/opts tests stay green
  • cargo test -p alkstore-postgres (harness server), clippy -D warnings, fmt clean; gates green server-less

References

  • docs/reviews/002-wave-4-general-review.md §Finding 3 + §Minor notes (the options bullet)
  • docs/architecture/engine-postgres.md (Connection architecture)
  • docs/architecture/decisions/008-contract-v1-pinning.md §6 (config split)
  • tasks/pg-engine-open-opts.md (the open task of record; Notes carry the connect-options SET mechanics this task extends)

Notes

To be filled by implementation agent

Summary

To be filled on completion