]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
fix(pool): more robust placement of reconnection attempts
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 00:23:50 +0000 (02:23 +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 0af6e354635c559d20f8281484471689b70dcba6..24671c07c63f47c8c6e879688f17c31203bb884e 100644 (file)
@@ -15,6 +15,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 17e747d5e2264b23ef730a661055e138a58a78e3..50da84b0a2ec19db3f46bb4780c7e771a141ae52 100644 (file)
@@ -676,22 +676,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 af4ab6fda2d99dce22cc49b311f6b9a99b6d2ccd..7dc4dd4d59156b0e85cbd04eca3a215622c8e18e 100644 (file)
@@ -731,24 +731,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)