test(ci): record which Postgres actually answered (#154) #326

Merged
bermudalamb merged 2 commits from fix/154-identify-the-answering-postgres into main 2026-09-09 10:49:04 -05:00
Owner

This does not fix the failure and does not guess at it. #154 has been wrong twice from reasoning ahead of evidence; this adds the measurement it identified in August and never took, so the next occurrence answers the question instead of reopening it.

Why the previous explanations are all dead

The observation that kills them: the schema comes back. A suite fails because orders does not exist, and a later suite truncating that same table passes. A dropped database does not un-drop itself.

Run 895 shows the same impossible pattern — PASS adminGate, FAIL schemaLoss, PASS adminVersion, with categoriesTags failing on missing tables in between.

So this was never one database losing its schema. More than one server answering to one name produces exactly this, and Docker's embedded DNS round-robins every container sharing an alias — a leftover service container from an earlier run fits every observation, including the empty dmesg that killed the OOM theory.

What this adds

globalSetup logs every address the database host resolves to. More than one is the answer outright. One address means this reading is wrong too, and the next suspect is a single container restarted with a fresh data directory.

Both globalSetup and a failing assertSchemaPresent record which server actually answered. pg_postmaster_start_time() is what settles that, and needs no special rights: two Postgres instances cannot share one. Differing values within a single run are proof, where a differing inet_server_addr alone could be argued to be one container that moved.

The failure message now tells the reader to compare the two, rather than leaving them to work out that this is the interesting comparison.

Three deliberate choices

  • Logged on passing runs too. A failing run's addresses mean nothing without a passing run's to compare against, and this issue has twice suffered from having only the failure to look at.
  • Neither probe can throw. A diagnostic that fails the run it was added to explain is worse than none — both are wrapped and degrade to a printed reason.
  • The failure path costs one extra round trip, taken only when the schema is already known to be missing. assertSchemaPresent is not on the hot path; resetDb calls it only after its TRUNCATE has already failed.

Why now

Run 895 reproduced this on main — 38 integration failures, 20 e2e, with relation "items" does not exist 37 times underneath assertion errors about tags and price filters. The same misdirection the issue documents.

Today is also the best case yet for the leftover-container theory: the runner had a six-deep backlog, and run 893 was killed mid-execution, which is precisely how a service container gets orphaned while keeping the postgres alias.

Verification

tsc clean · typecheck:tests clean · lint 0 errors, no new warnings.

Checked specifically: all four message patterns schemaLoss.integration.test.ts asserts on are still present, and the probe reads only pg_catalog functions — so it still answers against the dropped schema that suite deliberately creates.

Not verified by running the integration suite, which needs a database this machine cannot provide. The next CI run is what produces the measurement.

Refs #154

🤖 Generated with Claude Code

**This does not fix the failure and does not guess at it.** #154 has been wrong twice from reasoning ahead of evidence; this adds the measurement it identified in August and never took, so the next occurrence answers the question instead of reopening it. ## Why the previous explanations are all dead The observation that kills them: **the schema comes back.** A suite fails because `orders` does not exist, and a later suite truncating that same table passes. A dropped database does not un-drop itself. Run 895 shows the same impossible pattern — `PASS adminGate`, `FAIL schemaLoss`, `PASS adminVersion`, with `categoriesTags` failing on missing tables in between. So this was never one database losing its schema. **More than one server answering to one name** produces exactly this, and Docker's embedded DNS round-robins every container sharing an alias — a leftover service container from an earlier run fits every observation, including the empty `dmesg` that killed the OOM theory. ## What this adds **`globalSetup` logs every address the database host resolves to.** More than one is the answer outright. One address means this reading is wrong too, and the next suspect is a single container restarted with a fresh data directory. **Both `globalSetup` and a failing `assertSchemaPresent` record which server actually answered.** `pg_postmaster_start_time()` is what settles that, and needs no special rights: two Postgres instances cannot share one. Differing values within a single run are proof, where a differing `inet_server_addr` alone could be argued to be one container that moved. The failure message now tells the reader to compare the two, rather than leaving them to work out that this is the interesting comparison. ## Three deliberate choices - **Logged on passing runs too.** A failing run's addresses mean nothing without a passing run's to compare against, and this issue has twice suffered from having only the failure to look at. - **Neither probe can throw.** A diagnostic that fails the run it was added to explain is worse than none — both are wrapped and degrade to a printed reason. - **The failure path costs one extra round trip**, taken only when the schema is already known to be missing. `assertSchemaPresent` is not on the hot path; `resetDb` calls it only after its `TRUNCATE` has already failed. ## Why now Run 895 reproduced this on `main` — 38 integration failures, 20 e2e, with `relation "items" does not exist` **37 times** underneath assertion errors about tags and price filters. The same misdirection the issue documents. Today is also the best case yet for the leftover-container theory: the runner had a six-deep backlog, and **run 893 was killed mid-execution**, which is precisely how a service container gets orphaned while keeping the `postgres` alias. ## Verification `tsc` clean · `typecheck:tests` clean · lint 0 errors, no new warnings. Checked specifically: all four message patterns `schemaLoss.integration.test.ts` asserts on are still present, and the probe reads only `pg_catalog` functions — so it still answers against the dropped schema that suite deliberately creates. **Not verified by running the integration suite**, which needs a database this machine cannot provide. The next CI run is what produces the measurement. Refs #154 🤖 Generated with [Claude Code](https://claude.com/claude-code)
bermudalamb added 1 commit 2026-09-09 10:35:47 -05:00
test(ci): record which Postgres actually answered (#154)
SonarQube Analysis / sonarqube (pull_request) Failing after 30m38s
Linting / lint (pull_request) Successful in 2m58s
8e62f22ec9
This adds the measurement #154 has needed twice and never had. It does not fix the failure and does not guess at it: the issue has been wrong twice from reasoning ahead of evidence, and the point here is to make the next occurrence answer the question rather than reopen it.

The observation that rules out every explanation so far is that the schema comes back. A suite fails because orders does not exist, and a later suite truncating that same table passes. A dropped database does not un-drop itself, so this was never one database losing its schema. More than one server answering to one name produces exactly this, and Docker embedded DNS round-robins every container sharing an alias, so a leftover service container from an earlier run fits every observation including the empty dmesg that killed the OOM theory.

globalSetup now logs every address the database host resolves to. More than one is the answer outright. One address means this reading is wrong too, and the next suspect is a single container restarted with a fresh data directory.

Alongside it, both globalSetup and a failing assertSchemaPresent record which server actually answered. pg_postmaster_start_time is what settles that and needs no special rights: two Postgres instances cannot share one, so differing values within a single run are proof, where a differing inet_server_addr alone could be argued to be one container that moved. The failure message now says to compare the two rather than leaving the reader to know that is the interesting comparison.

Logged on a passing run as well as a failing one, deliberately. A failing run's addresses mean nothing without a passing run's to compare them against, and this issue has twice suffered from having only the failure to look at.

Neither can throw. A diagnostic that fails the run it was added to explain is worse than no diagnostic, so both are wrapped and both degrade to a printed reason.

The failure path costs one extra round trip, taken only when the schema is already known to be missing. assertSchemaPresent is not on the hot path — resetDb calls it only when its TRUNCATE has already failed.

Verified: tsc clean, typecheck:tests clean, lint 0 errors with no new warnings, and the four message patterns schemaLoss.integration.test.ts asserts on are all still present. The probe reads only pg_catalog functions, so it still answers against the dropped schema that suite creates.

Refs #154

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
bermudalamb added 1 commit 2026-09-09 10:48:54 -05:00
Merge branch 'main' into fix/154-identify-the-answering-postgres
SonarQube Analysis / sonarqube (pull_request) Failing after 24m39s
Linting / lint (pull_request) Successful in 3m31s
badf2d0241
bermudalamb merged commit 83b5b5e287 into main 2026-09-09 10:49:04 -05:00
bermudalamb deleted branch fix/154-identify-the-answering-postgres 2026-09-09 10:49:04 -05:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: bermudalamb/redefined-designs#326