Skip to content

ADR 0099 H2: convert the live-PG suite to engram-testkit; run the CI PG lane deeply parallel - #696

Merged
nikhilunni merged 2 commits into
mainfrom
h2-livepg-conversion
Jul 16, 2026
Merged

nikhilunni merged 2 commits into
mainfrom
h2-livepg-conversion

Conversation

@nikhilunni

Copy link
Copy Markdown
Contributor

Stacked on #695 (H1). Completes the per-test Postgres isolation arc of ADR 0099.

What

Tests — the remaining 19 coordinator live-PG files convert to engram_testkit::pg::fresh_db() (net −248 lines):

  • queue_scanner_live_pg.rs threads the per-test URL through its connect() helper so its AppStates, raw assertion pools, and PgListeners all point at the test's private database — previously three tests re-read the admin env var mid-test, which would now target an unmigrated database.
  • admin_chunk_gc_live_pg.rs retires its wipe_pin_set_state scrub helper: cleaning leaked shared-DB state is dead code under per-test clones.
  • Stale "shared database" comments updated throughout; skip behavior (ENGRAM_TEST_DATABASE_URL unset) unchanged.

CI (test-linux) — this is the "parallelize deeply" half:

  • Postgres moves from services: to plain docker run with -c max_connections=300 — service containers can't override the image CMD (same reason fake-gcs-server already uses docker run), and connection headroom is what actually gates deep parallelism: each test's PostgresStore holds up to an 8-connection pool.
  • The readiness wait forces TCP (pg_isready -h 127.0.0.1): initdb's temporary bootstrap server listens on the unix socket only, so a socket probe can report ready prematurely.
  • The Postgres-gated step goes --test-threads=1 → --test-threads=16 (PG-IO-bound tests; oversubscribing the 4 vcpus; 16 × worst-case ~17 connections < 300).
  • deploy/docker-compose.dev.yml postgres gets the same max_connections=300 so local runs go equally deep.

Verification

  • Full 22-binary lane (143 tests) at --test-threads=16 against local PG: green 3× consecutively, ~12–22 s wall — previously fully serial. (One intermittent nextest leaky info-flag: a spawned listener task outliving its test process; pre-existing behavior, passes.)
  • just check green (1678 passed).
  • ci.yml + compose validated with yaml.safe_load; actionlint delta clean (only pre-existing custom runner-label warnings).

Follow-on ceilings (not this PR)

Template cloning is serialized under an advisory lock (~100–300 ms/test ⇒ a few seconds of serial floor at current suite size); after that, the runner size itself is the next lever.

🤖 Generated with Claude Code

nikhilunni and others added 2 commits July 16, 2026 14:08
…ases

New dev-only crate engram-testkit with pg::fresh_db(): clone each
test's database from a migrated template (~100-300ms vs replaying the
full migration chain). The template name fingerprints the embedded
migrator's (version, checksum) pairs so a migration change mints a new
template automatically; bootstrap publishes via CREATE-as-wip +
ALTER RENAME so a crash mid-migrate never leaves a half-built template
looking valid; bootstrap and clones are serialized under a
session-scoped advisory lock (concurrent CREATE DATABASE ... TEMPLATE
fails on 'source database is being accessed', and nextest is
process-per-test so an in-process guard is not enough). Per-test DBs
are leaked (CI Postgres is ephemeral); template bootstrap sweeps
testkit-named databases older than 3h on long-lived dev instances.

Convert the three proof tests:
- ha_listener.rs (all four tests) — the binary that forced the CI PG
  lane to --test-threads=1: both LISTEN/NOTIFY tests cross-talked on
  the shared database's session_events channel. NOTIFY is
  per-database, so private clones make the class impossible.
- admin_evac_live_pg.rs / enable_reuse_live_pg.rs — replace their
  bespoke CREATE DATABASE blocks (the pattern this crate generalizes).
  migration_0037 schema assertions now inspect the rig's own database
  instead of the shared admin database (which nothing migrates
  anymore).

Verified: 16 tests across the three binaries pass under default
nextest parallelism 5x consecutively against local PG; skip path
(env unset) intact; just check green (1678 passed).

The remaining ~19 live_pg files convert in the follow-up (H2), which
then drops --test-threads=1 from ci.yml.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…PG lane deeply parallel

Convert the remaining 19 coordinator live-PG test files to
engram_testkit::pg::fresh_db() — every test now runs against its own
template-cloned database. queue_scanner_live_pg threads the per-test
URL through its connect() helper so its AppStates, raw pools, and
PgListeners all point at the test's private database (previously three
tests re-read the admin env var mid-test). admin_chunk_gc retires its
wipe_pin_set_state helper — scrubbing leaked shared-DB state is dead
code under per-test clones. Stale shared-database comments updated
throughout.

CI (ci.yml test-linux):
- Postgres moves from a services: container to plain docker run with
  -c max_connections=300 (service containers can't override CMD —
  same reason fake-gcs-server already uses docker run). Readiness
  wait forces TCP (-h 127.0.0.1): initdb's temporary bootstrap server
  listens on the unix socket only, so a socket pg_isready can report
  ready prematurely.
- The Postgres-gated step drops --test-threads=1 for
  --test-threads=16: the tests are PG-IO-bound, so oversubscribe the
  4 vcpus; 16 threads x worst-case ~17 connections stays under 300.
- The dev compose postgres gets the same max_connections=300 so local
  runs can go equally deep.

Verified: the full 22-binary lane (143 tests) passes at
--test-threads=16 against local PG 3x consecutively, ~12-22s wall
(previously fully serial); just check green (1678 passed);
ci.yml + compose validated with yaml.safe_load, actionlint delta
clean (only pre-existing custom runner-label warnings).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

The latest Buf updates on your PR. Results from workflow CI / buf (pull_request).

BuildFormatLintBreakingUpdated (UTC)
✅ passed⏩ skipped⏩ skipped✅ passedJul 16, 2026, 9:21 PM

Base automatically changed from h1-testkit-pg-isolation to main July 16, 2026 21:23
@nikhilunni
nikhilunni merged commit f7f91b6 into main Jul 16, 2026
19 checks passed
@nikhilunni
nikhilunni deleted the h2-livepg-conversion branch July 16, 2026 21:38
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