From cc46ea711df77540d5d658e9c7b3ab1e88288929 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Thu, 2 Dec 2021 09:18:11 -0500 Subject: propose concurrency check for SessionTransaction the discussion at #7387 refers to a condition that seems to happen in the wild also, such as [1] [2] [3], it's not entirely clear why this specific spot is how this occurs, however it's maybe that when the connection is being acquired from the pool, under load there might be a wait on the connection pool, leading to more time for another errant thread to be calling .close(), just a theory. in this patch we propose using decorators and context managers along with declarative state declarations to block reentrant or concurrent calls to methods that conflict with expected state changes. The :class:`_orm.Session` (and by extension :class:`.AsyncSession`) now has new state-tracking functionality that will proactively trap any unexpected state changes which occur as a particular transactional method proceeds. This is to allow situations where the :class:`_orm.Session` is being used in a thread-unsafe manner, where event hooks or similar may be calling unexpected methods within operations, as well as potentially under other concurrency situations such as asyncio or gevent to raise an informative message when the illegal access first occurs, rather than passing silently leading to secondary failures due to the :class:`_orm.Session` being in an invalid state. [1] https://stackoverflow.com/questions/25768428/sqlalchemy-connection-errors [2] https://groups.google.com/g/sqlalchemy/c/n5oVX3v4WOw [3] https://github.com/cosmicpython/code/issues/23 Fixes: #7433 Change-Id: I699b935c0ec4e5a63f12cf878af6f7a92a30a3aa --- lib/sqlalchemy/exc.py | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'lib/sqlalchemy/exc.py') diff --git a/lib/sqlalchemy/exc.py b/lib/sqlalchemy/exc.py index e35c41836..e51214fd9 100644 --- a/lib/sqlalchemy/exc.py +++ b/lib/sqlalchemy/exc.py @@ -249,6 +249,15 @@ class InvalidRequestError(SQLAlchemyError): """ +class IllegalStateChangeError(InvalidRequestError): + """An object that tracks state encountered an illegal state change + of some kind. + + .. versionadded:: 2.0 + + """ + + class NoInspectionAvailable(InvalidRequestError): """A subject passed to :func:`sqlalchemy.inspection.inspect` produced no context for inspection.""" -- cgit v1.2.1