From: Mike Bayer Date: Mon, 7 Jun 2021 15:28:49 +0000 (-0400) Subject: Add asyncio.TimeoutError as an exit exception X-Git-Tag: rel_1_4_18~8 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2fa39312b2c878b717d4c4f41380e5a8931eb374;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git Add asyncio.TimeoutError as an exit exception Added ``asyncio.exceptions.TimeoutError``, ``asyncio.exceptions.CancelledError`` as so-called "exit exceptions", a class of exceptions that include things like ``GreenletExit`` and ``KeyboardInterrupt``, which are considered to be events that warrant considering a DBAPI connection to be in an unusable state where it should be recycled. Fixes: #6592 Change-Id: Idcfa7aaa2d7660838b907388db9c6457afa6edbd --- diff --git a/doc/build/changelog/unreleased_14/6592.rst b/doc/build/changelog/unreleased_14/6592.rst new file mode 100644 index 0000000000..896789bd53 --- /dev/null +++ b/doc/build/changelog/unreleased_14/6592.rst @@ -0,0 +1,10 @@ +.. change:: + :tags: bug, asyncio + :tickets: 6592 + + Added ``asyncio.exceptions.TimeoutError``, + ``asyncio.exceptions.CancelledError`` as so-called "exit exceptions", a + class of exceptions that include things like ``GreenletExit`` and + ``KeyboardInterrupt``, which are considered to be events that warrant + considering a DBAPI connection to be in an unusable state where it should + be recycled. diff --git a/lib/sqlalchemy/engine/base.py b/lib/sqlalchemy/engine/base.py index 663482b1f5..64f638a50d 100644 --- a/lib/sqlalchemy/engine/base.py +++ b/lib/sqlalchemy/engine/base.py @@ -1877,7 +1877,7 @@ class Connection(Connectable): ): exc_info = sys.exc_info() - is_exit_exception = not isinstance(e, Exception) + is_exit_exception = util.is_exit_exception(e) if not self._is_disconnect: self._is_disconnect = ( @@ -2325,7 +2325,6 @@ class Transaction(TransactionalContext): phase transactions may be used. """ - try: self._do_commit() finally: diff --git a/lib/sqlalchemy/util/__init__.py b/lib/sqlalchemy/util/__init__.py index 89d09f930f..db39668498 100644 --- a/lib/sqlalchemy/util/__init__.py +++ b/lib/sqlalchemy/util/__init__.py @@ -101,6 +101,7 @@ from .concurrency import asyncio from .concurrency import await_fallback from .concurrency import await_only from .concurrency import greenlet_spawn +from .concurrency import is_exit_exception from .deprecations import deprecated from .deprecations import deprecated_20 from .deprecations import deprecated_20_cls diff --git a/lib/sqlalchemy/util/_concurrency_py3k.py b/lib/sqlalchemy/util/_concurrency_py3k.py index 3b60e6584a..88294557d7 100644 --- a/lib/sqlalchemy/util/_concurrency_py3k.py +++ b/lib/sqlalchemy/util/_concurrency_py3k.py @@ -10,7 +10,6 @@ from . import compat from .langhelpers import memoized_property from .. import exc - if compat.py37: try: from contextvars import copy_context as _copy_context @@ -25,6 +24,12 @@ else: _copy_context = None +def is_exit_exception(e): + return not isinstance(e, Exception) or isinstance( + e, (asyncio.TimeoutError, asyncio.CancelledError) + ) + + # implementation based on snaury gist at # https://gist.github.com/snaury/202bf4f22c41ca34e56297bae5f33fef # Issue for context: https://github.com/python-greenlet/greenlet/issues/173 diff --git a/lib/sqlalchemy/util/concurrency.py b/lib/sqlalchemy/util/concurrency.py index 60db9cfff5..4635473191 100644 --- a/lib/sqlalchemy/util/concurrency.py +++ b/lib/sqlalchemy/util/concurrency.py @@ -12,6 +12,7 @@ if compat.py3k: from ._concurrency_py3k import await_only from ._concurrency_py3k import await_fallback from ._concurrency_py3k import greenlet_spawn + from ._concurrency_py3k import is_exit_exception from ._concurrency_py3k import AsyncAdaptedLock from ._concurrency_py3k import _util_async_run # noqa F401 from ._concurrency_py3k import ( @@ -36,6 +37,9 @@ if not have_greenlet: "the greenlet library is required to use this function." ) + def is_exit_exception(e): # noqa F811 + return not isinstance(e, Exception) + def await_only(thing): # noqa F811 _not_implemented()