From b08410547a022d01654c6bdc7efe394c34e1ed5d Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Sat, 18 Oct 2025 17:48:32 +0200 Subject: [PATCH] fix(pool): more robust placement of reconnection attempts The problem reported in #1176 is the close recursion already fixed. However, because we try to reconnect before closing, we end up scheduling a reconnection attempt for every recursion loop. The recursion shouldn't happen anymore, but it seems more robust to reconnect after the connection has been successfully closed, otherwise we might end up requesting more connections than we ought (hopefully not as dramatically as here anyway). --- docs/news_pool.rst | 2 ++ psycopg_pool/psycopg_pool/pool.py | 6 +++--- psycopg_pool/psycopg_pool/pool_async.py | 6 +++--- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/docs/news_pool.rst b/docs/news_pool.rst index 506cb1608..4b3547b49 100644 --- a/docs/news_pool.rst +++ b/docs/news_pool.rst @@ -22,6 +22,8 @@ psycopg_pool 3.2.7 (unreleased) - Fix infinite loop with connections modified to return on close (:ticket:`#1124`). +- Fix request of excessive connections upon connection close failing and + retrying (:ticket:`#1176`). Current release diff --git a/psycopg_pool/psycopg_pool/pool.py b/psycopg_pool/psycopg_pool/pool.py index d8411d070..68cb8b899 100644 --- a/psycopg_pool/psycopg_pool/pool.py +++ b/psycopg_pool/psycopg_pool/pool.py @@ -688,22 +688,22 @@ class ConnectionPool(Generic[CT], BasePool): if conn.pgconn.transaction_status == TransactionStatus.UNKNOWN: self._stats[self._CONNECTIONS_LOST] += 1 # Connection no more in working state: create a new one. - self.run_task(AddConnection(self)) logger.info("not serving connection found broken") + self.run_task(AddConnection(self)) return elif conn.pgconn.transaction_status == TransactionStatus.UNKNOWN: self._stats[self._RETURNS_BAD] += 1 # Connection no more in working state: create a new one. - self.run_task(AddConnection(self)) logger.warning("discarding closed connection: %s", conn) + self.run_task(AddConnection(self)) return # Check if the connection is past its best before date if conn._expire_at <= monotonic(): - self.run_task(AddConnection(self)) logger.info("discarding expired connection") conn._pool = None conn.close() + self.run_task(AddConnection(self)) return self._add_to_pool(conn) diff --git a/psycopg_pool/psycopg_pool/pool_async.py b/psycopg_pool/psycopg_pool/pool_async.py index 99e6b00bb..7441c3a70 100644 --- a/psycopg_pool/psycopg_pool/pool_async.py +++ b/psycopg_pool/psycopg_pool/pool_async.py @@ -738,24 +738,24 @@ class AsyncConnectionPool(Generic[ACT], BasePool): if conn.pgconn.transaction_status == TransactionStatus.UNKNOWN: self._stats[self._CONNECTIONS_LOST] += 1 # Connection no more in working state: create a new one. - self.run_task(AddConnection(self)) logger.info("not serving connection found broken") + self.run_task(AddConnection(self)) return else: if conn.pgconn.transaction_status == TransactionStatus.UNKNOWN: self._stats[self._RETURNS_BAD] += 1 # Connection no more in working state: create a new one. - self.run_task(AddConnection(self)) logger.warning("discarding closed connection: %s", conn) + self.run_task(AddConnection(self)) return # Check if the connection is past its best before date if conn._expire_at <= monotonic(): - self.run_task(AddConnection(self)) logger.info("discarding expired connection") conn._pool = None await conn.close() + self.run_task(AddConnection(self)) return await self._add_to_pool(conn) -- 2.47.3