]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
enable check same thread for aiosqlite
authorMike Bayer <mike_mp@zzzcomputing.com>
Tue, 11 Oct 2022 18:22:40 +0000 (14:22 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Tue, 11 Oct 2022 18:29:28 +0000 (14:29 -0400)
to do this we have to invent our own isolation level
setter based on their current internals.   however
now we can ensure thread-safe access.  we are trying
to resolve an issue where test suite on CI seems to fail
around the same time each time.

Change-Id: I79c8fc04b9afef0876fb446ad40a7621a772cd34

lib/sqlalchemy/dialects/sqlite/aiosqlite.py

index 97ea1b2b363a4b650d5c4790ab77d24d140b175b..c3926e12158d11429f9b62d6d2a6abf6ff45fcd7 100644 (file)
@@ -47,6 +47,9 @@ in Python and use them directly in SQLite queries as described here: :ref:`pysql
 
 """  # noqa
 
+import asyncio
+from functools import partial
+
 from .base import SQLiteExecutionContext
 from .pysqlite import SQLiteDialect_pysqlite
 from ... import pool
@@ -187,8 +190,22 @@ class AsyncAdapt_aiosqlite_connection(AdaptedConnection):
 
     @isolation_level.setter
     def isolation_level(self, value):
+
+        # aiosqlite's isolation_level setter works outside the Thread
+        # that it's supposed to, necessitating setting check_same_thread=False.
+        # for improved stability, we instead invent our own awaitable version
+        # using aiosqlite's async queue directly.
+
+        def set_iso(connection, value):
+            connection.isolation_level = value
+
+        function = partial(set_iso, self._connection._conn, value)
+        future = asyncio.get_event_loop().create_future()
+
+        self._connection._tx.put_nowait((future, function))
+
         try:
-            self._connection.isolation_level = value
+            return self.await_(future)
         except Exception as error:
             self._handle_exception(error)
 
@@ -272,18 +289,6 @@ class AsyncAdapt_aiosqlite_dbapi:
     def connect(self, *arg, **kw):
         async_fallback = kw.pop("async_fallback", False)
 
-        # Q. WHY do we need this?
-        # A. Because there is no way to set connection.isolation_level
-        #    otherwise
-        # Q. BUT HOW do you know it is SAFE ?????
-        # A. The only operation that isn't safe is the isolation level set
-        #    operation which aiosqlite appears to have let slip through even
-        #    though pysqlite appears to do check_same_thread for this.
-        #    All execute operations etc. should be safe because they all
-        #    go through the single executor thread.
-
-        kw["check_same_thread"] = False
-
         connection = self.aiosqlite.connect(*arg, **kw)
 
         # it's a Thread.   you'll thank us later