Skip to content

Commit 87b4e6a

Browse files
docs(pool): log and document ROLLBACK-failure connection drop
When _reset_connection cannot ROLLBACK a connection (socket dead or the ROLLBACK itself raises), the pool drops it. Emit a DEBUG log line so operators tracking pool churn can see the reason, and expand the docstring to explain why dropping is the right call (Raft log cleans up uncommitted work). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 71e0fab commit 87b4e6a

File tree

1 file changed

+21
-1
lines changed

1 file changed

+21
-1
lines changed

src/dqliteclient/pool.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import asyncio
44
import contextlib
5+
import logging
56
from collections.abc import AsyncIterator, Sequence
67
from contextlib import asynccontextmanager
78
from typing import Any
@@ -12,6 +13,8 @@
1213
from dqliteclient.node_store import NodeStore
1314
from dqliteclient.protocol import _validate_max_total_rows
1415

16+
logger = logging.getLogger(__name__)
17+
1518

1619
def _socket_looks_dead(conn: DqliteConnection) -> bool:
1720
"""Best-effort local detection of a half-closed TCP socket.
@@ -290,16 +293,33 @@ async def _reset_connection(self, conn: DqliteConnection) -> bool:
290293
291294
Returns True if the connection is clean and can be reused,
292295
False if it should be destroyed.
296+
297+
If ROLLBACK raises, the connection's transaction state is
298+
unknowable from the client's side — the wire request may have
299+
been half-sent, or delivered but not acknowledged. The pool
300+
therefore drops the connection; the dqlite cluster's Raft log
301+
eventually reclaims any uncommitted work from the terminated
302+
session. A DEBUG log entry is emitted to help operators
303+
diagnose churning pools.
293304
"""
294305
if conn._in_transaction:
295306
# Cheap pre-write liveness check: if the transport is already
296307
# closing or the reader has seen EOF, ROLLBACK would stall on
297308
# _read_data until self._timeout. Bail fast instead.
298309
if _socket_looks_dead(conn):
310+
logger.debug(
311+
"pool: dropping connection %s (socket looks dead before ROLLBACK)",
312+
conn._address,
313+
)
299314
return False
300315
try:
301316
await conn.execute("ROLLBACK")
302-
except BaseException:
317+
except BaseException as exc:
318+
logger.debug(
319+
"pool: dropping connection %s after ROLLBACK failure: %r",
320+
conn._address,
321+
exc,
322+
)
303323
return False
304324
conn._in_transaction = False
305325
conn._tx_owner = None

0 commit comments

Comments
 (0)