Skip to content

fix(db): require asyncpg>=0.32 so a dropped connection can't wedge the worker - #6107

Open
nicoloboschi wants to merge 1 commit into
mainfrom
triage/6067
Open

nicoloboschi wants to merge 1 commit into
mainfrom
triage/6067

Conversation

@nicoloboschi

Copy link
Copy Markdown
Collaborator

Fixes #6067.

Problem

On asyncpg <= 0.31, when a worker claim query timed out and its connection then dropped, the transaction's ROLLBACK waited forever. The poll loop stopped claiming work with nothing logged, /health stayed 200, and operations piled up as pending until a restart. The 1.1.0 image ships asyncpg 0.31.0.

Fix

Raise the floor to asyncpg>=0.32.0 (lock: only asyncpg changes). 0.32 resolves pending cancellations when the connection is lost (MagicStack/asyncpg#1361) and bounds that wait by the command timeout (#1370). It's fixed at the source, so every transaction is covered, not just the worker claim.

Behaviour changes

  • A dropped connection now fails the claim with InterfaceError: connection is closed; the poll loop logs it and carries on.
  • asyncpg 0.32 keeps the pool at min_size connections even when idle (before, idle ones could close and the pool could drain to zero). Default is 5; documented on HINDSIGHT_API_DB_POOL_MIN_SIZE, set 0 to allow draining.

Tests

  • New tests/test_db_dropped_connection.py: proxy swallows replies, query times out, connection drops. Fails on 0.31 (stuck in ROLLBACK after 10s), passes on 0.32 (~2s, stable over 5 runs).
  • Pool / DB / worker tests: 330 passed, 5 skipped, 1 failure (Oracle test that needs oracledb, not installed locally; unrelated).

…e worker (#6067)

asyncpg <= 0.31 left a timed-out query's cancellation pending until the
server answered it. When the connection died first, every later query on
it awaited forever, including the ROLLBACK from transaction().__aexit__,
so the worker's claim loop stopped silently while /health stayed green.
asyncpg 0.32.0 resolves pending cancellations on connection loss and
bounds the wait by the command timeout.

Adds a regression test that drives PostgresConnection.transaction()
through a proxy that swallows replies then drops the connection; it fails
on 0.31 and passes on 0.32.

0.32 also makes the pool's min_size a maintained floor (idle connections
are no longer closed below it); documented on HINDSIGHT_API_DB_POOL_MIN_SIZE.

This branch has not been deployed

No deployments
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.

Worker poller hangs forever in ROLLBACK after a timed-out claim when the connection drops (asyncpg ≤ 0.31; fixed in 0.32)

1 participant