]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
refactor: clearer cancel_safe implementation
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>
Wed, 10 Apr 2024 20:37:24 +0000 (22:37 +0200)
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>
Fri, 12 Apr 2024 22:10:44 +0000 (00:10 +0200)
Avoid catching NotSupported, just check for the libpq version.

Also avoid the half exception handler in `_cancel_gen()`: as in the
legacy branch, warn and ignore any error happening in the outermost
method, without adding an ignore exception policy in an implementation
method.

Close #778.

psycopg/psycopg/_connection_base.py
psycopg/psycopg/connection.py
psycopg/psycopg/connection_async.py

index 4944f1d3157b02626b65ba8d32819cbbff2eba9c..3d876f11ecc64e41e27ba361ff462d4c6143cb38 100644 (file)
@@ -320,13 +320,9 @@ class BaseConnection(Generic[Row]):
         return True
 
     def _cancel_gen(self) -> PQGenConn[None]:
-        try:
-            cancel_conn = self.pgconn.cancel_conn()
-        except e.OperationalError as ex:  # if the connection is closed
-            logger.warning("couldn't create a cancel connection: %s", ex)
-        else:
-            cancel_conn.start()
-            yield from generators.cancel(cancel_conn)
+        cancel_conn = self.pgconn.cancel_conn()
+        cancel_conn.start()
+        yield from generators.cancel(cancel_conn)
 
     def add_notice_handler(self, callback: NoticeHandler) -> None:
         """
index 80e2b66da26a9ded388885797d63f594e28cd313..ec334d1227ca5f21e42a8eadbe8254b07dfee5b1 100644 (file)
@@ -271,11 +271,17 @@ class Connection(BaseConnection[Row]):
         If the underlying libpq is older than version 17, the method will fall
         back to using the same implementation of `!cancel()`.
         """
-        if self._should_cancel():
+        if not self._should_cancel():
+            return
+
+        # TODO: replace with capabilities.has_safe_cancel after merging #782
+        if pq.__build_version__ >= 170000:
             try:
                 waiting.wait_conn(self._cancel_gen(), interval=_WAIT_INTERVAL)
-            except e.NotSupportedError:
-                self.cancel()
+            except Exception as ex:
+                logger.warning("couldn't try to cancel query: %s", str(ex))
+        else:
+            self.cancel()
 
     @contextmanager
     def transaction(
index 61444a31cd46f2608ba1052e24b1cf0e7353fc21..8f36bf63eaec8b367bc727367ce02844462f48b4 100644 (file)
@@ -288,16 +288,23 @@ class AsyncConnection(BaseConnection[Row]):
         If the underlying libpq is older than version 17, the method will fall
         back to using the same implementation of `!cancel()`.
         """
-        if self._should_cancel():
+        if not self._should_cancel():
+            return
+
+        # TODO: replace with capabilities.has_safe_cancel after merging #782
+        if pq.__build_version__ >= 170000:
             try:
                 await waiting.wait_conn_async(
                     self._cancel_gen(), interval=_WAIT_INTERVAL
                 )
-            except e.NotSupportedError:
-                if True:  # ASYNC
-                    await to_thread(self.cancel)
-                else:
-                    self.cancel()
+            except Exception as ex:
+                logger.warning("couldn't try to cancel query: %s", str(ex))
+
+        else:
+            if True:  # ASYNC
+                await to_thread(self.cancel)
+            else:
+                self.cancel()
 
     @asynccontextmanager
     async def transaction(