Conversation
With `fetch_types: false`, a queued `reserve()` on a cold pool never settled: the ReadyForQuery handler returned early instead of falling through to `onopen()`, so nothing resolved the reserve. Fall through to match the `fetch_types: true` path, and add a cold-pool regression test.
|
Looks good, quick fix, test and comment guard against a random change of flow with the reintroduction of a |
Author
|
Verified against a real Postgres instance:
The regression test I added ( |
2 tasks
spy4x
added a commit
to spy4x/ts-libs
that referenced
this pull request
Sep 24, 2026
The old test's SET client_min_messages query warmed the pool the same way the fix's own warm-up does, so removing the fix left the test green. Move client_min_messages into the connection options and send no query before runMigrations, so the hang reproduces again (~5s, then red). Force-close the client in finally instead of a graceful end + query, which used to hand the stuck reserve() a connection and recreate the table it was supposed to drop. porsager/postgres#1220 is an open, unmerged third-party PR against the bug filed as #1219 — not a landed upstream fix. Corrected in the doc comment, the test and README, and named the one race the workaround does not close.
spy4x
added a commit
to spy4x/ts-libs
that referenced
this pull request
Sep 24, 2026
* fix(server): unhang runMigrations on fetch_types: false sql.reserve() never resolved when it had to open a fresh connection on a client built with fetch_types: false — postgres@3.4.7's ReadyForQuery only hands a new connection back to a pending reserve() through the branch that also fetches array-type OIDs, which fetch_types: false skips (upstream: porsager/postgres#1220). A plain query on the pool before reserve() leaves a connection idle, so reserve() takes the pool's synchronous already-idle path and never hits the buggy one. * fix(server): repair fetch_types test and PR reference The old test's SET client_min_messages query warmed the pool the same way the fix's own warm-up does, so removing the fix left the test green. Move client_min_messages into the connection options and send no query before runMigrations, so the hang reproduces again (~5s, then red). Force-close the client in finally instead of a graceful end + query, which used to hand the stuck reserve() a connection and recreate the table it was supposed to drop. porsager/postgres#1220 is an open, unmerged third-party PR against the bug filed as #1219 — not a landed upstream fix. Corrected in the doc comment, the test and README, and named the one race the workaround does not close. * docs(server): correct the reserve race wording The stuck connection is freed by max_lifetime, and a query after reserve() never runs; both from the round-2 reviewer of #167.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1219.
reserve()on a cold pool never settles whenfetch_types: false: theReadyForQueryhandler returns early instead of falling through toonopen(), so nothing resolves the reserve. Withfetch_types: truethe array-type fetch round trip falls through and resolves it, which is why it only reproduces with the option disabled.This makes the non-fetching path fall through to
onopen()wheninitialis a reserve, and adds a cold-pool regression test.