]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
fix(pool): more robust placement of reconnection attempts 1067/head
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>
Sat, 18 Oct 2025 15:48:32 +0000 (17:48 +0200)
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>
Sun, 19 Oct 2025 01:32:16 +0000 (03:32 +0200)
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
psycopg_pool/psycopg_pool/pool.py
psycopg_pool/psycopg_pool/pool_async.py

index 506cb16081c8419f56f0c9c30bc0eb3605891a91..4b3547b49b1723a376acaff4c39646c7fbb2d27d 100644 (file)
@@ -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
index d8411d070ea93b51e5fa5c7b528092f84d86f336..68cb8b899754c971fd26a2a11b6d5484e592ac77 100644 (file)
@@ -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)
index 99e6b00bb684c55082c009453ebd8cd4cbc9d2df..7441c3a70bfe1e2728603c8c1f968a4e26d55a79 100644 (file)
@@ -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)