You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Under concurrent cold-starts (many PGlite instances started at once, for example pytest-xdist with more workers than the machine has cores), a fraction of instances reach a state where the pglite-socket TCP server is listening but the Postgres backend never completes a client connection. PGliteManager.start() reports the instance ready (it only checks that a bare TCP connect succeeds), and every real connection to that instance then hangs until it times out.
Symptoms
psycopg.errors.ConnectionTimeout (not connection-refused) on the first real query.
The node process is alive, with no error and no crash. Its last stdout line is Server started on TCP 127.0.0.1:<port>, then silence.
Start N PGliteManager(use_tcp=True) instances concurrently, process-parallel so each has its own work directory, and after each start() returns, open a real connection with a short connect_timeout and run SELECT 1. On an oversubscribed machine a fraction time out even though start() reported success.
Matched runs, 24 concurrent cold-starts x 8 rounds (192 starts) on a 10-core machine, changing only the pglite / pglite-socket versions:
The hang rate scales with how much the run oversubscribes the CPU (workers per core), consistent with starvation of the single-threaded node/WASM backend. It also reproduces at lower rates with milder oversubscription and on Linux CI.
The only difference between the two rows above is the pglite and pglite-socket versions, and PR #52 ("update pglite 0.5.0, allow multiple concurrent connections") bumps exactly those. With those versions the hang does not reproduce at all (0 / 192). So merging #52 appears to resolve this.
#54 is complementary rather than an alternative: it makes wait_for_ready fail fast if a backend is ever unreachable, but it does not fix the hang itself. #52 does.
Environment
py-pglite 0.5.3, TCP mode, macOS (10 cores) and Linux CI.
Summary
Under concurrent cold-starts (many PGlite instances started at once, for example pytest-xdist with more workers than the machine has cores), a fraction of instances reach a state where the pglite-socket TCP server is listening but the Postgres backend never completes a client connection.
PGliteManager.start()reports the instance ready (it only checks that a bare TCP connect succeeds), and every real connection to that instance then hangs until it times out.Symptoms
psycopg.errors.ConnectionTimeout(not connection-refused) on the first real query.Server started on TCP 127.0.0.1:<port>, then silence.wait_for_readyretries 15 times atconnect_timeout=60), this stalls for about 15 minutes before failing. That long stall is a separate, defensive fix in Lower readiness connect_timeout so wait_for_ready fails fast on a hung backend #54.Reproduction and measured rates
Start N
PGliteManager(use_tcp=True)instances concurrently, process-parallel so each has its own work directory, and after eachstart()returns, open a real connection with a shortconnect_timeoutand runSELECT 1. On an oversubscribed machine a fraction time out even thoughstart()reported success.Matched runs, 24 concurrent cold-starts x 8 rounds (192 starts) on a 10-core machine, changing only the pglite / pglite-socket versions:
@electric-sql/pglite/pglite-socket^0.3.0/^0.0.8(current main)^0.5.0/^0.2.1(from #52)The hang rate scales with how much the run oversubscribes the CPU (workers per core), consistent with starvation of the single-threaded node/WASM backend. It also reproduces at lower rates with milder oversubscription and on Linux CI.
This looks fixed by #52
The only difference between the two rows above is the pglite and pglite-socket versions, and PR #52 ("update pglite 0.5.0, allow multiple concurrent connections") bumps exactly those. With those versions the hang does not reproduce at all (0 / 192). So merging #52 appears to resolve this.
#54 is complementary rather than an alternative: it makes
wait_for_readyfail fast if a backend is ever unreachable, but it does not fix the hang itself. #52 does.Environment
py-pglite 0.5.3, TCP mode, macOS (10 cores) and Linux CI.