SQLite objects created in a thread can only be used in that same thread
Ideas on solving that (derived from discussion in MR !11 (merged)):
- A) Using Asyncio - I've created a ticket for that POC: Use Asyncio instead of Threads (#97), but considering it "nice to have" and not worth the effort just for SQLite support. Which we currently don't even need.
- B) provide an interface for using thread-local database sessions (e.g. spawn a new database session in new threads and extend the
DB.session
interface accordingly) - C) AFAIR most threads access the DB objects in a reading manner only. So they could be detached from the database and/or eager loaded.
- D) Getting rid of ORM and DB for caching altogether. Using the heavy foundation of a full database and ORM has historic reasons. Not long ago even Redis was part of the chain. Using it just for caching is a bit overhead IMO. We could only cache the playout API endpoint and hold the programme in memory. But that's food for thought for a later stage i guess.
Considered low-priority as we have no hard requirement for SQLite or might skip DB+ORM altogether (see [EPIC] Schedule programme data model without OR... (#100 - closed)).
Stacktrace
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/usr/lib/python3.9/threading.py", line 973, in _bootstrap_inner
self.run()
File "/usr/lib/python3.9/threading.py", line 910, in run
self._target(*self._args, **self._kwargs)
File "/home/david/code/aura/engine-sumpfralle/src/events.py", line 253, in func
self.call_event("on_metadata", data)
File "/home/david/code/aura/engine-sumpfralle/src/events.py", line 148, in call_event
method(*args)
File "/home/david/code/aura/engine-sumpfralle/src/plugins/trackservice.py", line 156, in on_metadata
self.store_clock_info(data)
File "/home/david/code/aura/engine-sumpfralle/src/plugins/trackservice.py", line 213, in store_clock_info
if e.meta_data:
File "/usr/lib/python3/dist-packages/sqlalchemy/orm/attributes.py", line 294, in __get__
return self.impl.get(instance_state(instance), dict_)
File "/usr/lib/python3/dist-packages/sqlalchemy/orm/attributes.py", line 730, in get
value = self.callable_(state, passive)
File "/usr/lib/python3/dist-packages/sqlalchemy/orm/strategies.py", line 759, in _load_for_state
return self._emit_lazyload(
File "<string>", line 1, in <lambda>
File "/usr/lib/python3/dist-packages/sqlalchemy/orm/strategies.py", line 900, in _emit_lazyload
q(session)
File "/usr/lib/python3/dist-packages/sqlalchemy/ext/baked.py", line 544, in all
return list(self)
File "/usr/lib/python3/dist-packages/sqlalchemy/ext/baked.py", line 444, in __iter__
return q._execute_and_instances(context)
File "/usr/lib/python3/dist-packages/sqlalchemy/orm/query.py", line 3560, in _execute_and_instances
result = conn.execute(querycontext.statement, self._params)
File "/usr/lib/python3/dist-packages/sqlalchemy/engine/base.py", line 1011, in execute
return meth(self, multiparams, params)
File "/usr/lib/python3/dist-packages/sqlalchemy/sql/elements.py", line 298, in _execute_on_connection
return connection._execute_clauseelement(self, multiparams, params)
File "/usr/lib/python3/dist-packages/sqlalchemy/engine/base.py", line 1124, in _execute_clauseelement
ret = self._execute_context(
File "/usr/lib/python3/dist-packages/sqlalchemy/engine/base.py", line 1206, in _execute_context
self._handle_dbapi_exception(
File "/usr/lib/python3/dist-packages/sqlalchemy/engine/base.py", line 1510, in _handle_dbapi_exception
util.raise_(
File "/usr/lib/python3/dist-packages/sqlalchemy/util/compat.py", line 182, in raise_
raise exception
File "/usr/lib/python3/dist-packages/sqlalchemy/engine/base.py", line 1204, in _execute_context
context = constructor(dialect, self, conn, *args)
File "/usr/lib/python3/dist-packages/sqlalchemy/engine/default.py", line 822, in _init_compiled
self.cursor = self.create_cursor()
File "/usr/lib/python3/dist-packages/sqlalchemy/engine/default.py", line 1178, in create_cursor
return self._dbapi_connection.cursor()
File "/usr/lib/python3/dist-packages/sqlalchemy/pool/base.py", line 1000, in cursor
return self.connection.cursor(*args, **kwargs)
sqlalchemy.exc.ProgrammingError: (sqlite3.ProgrammingError) SQLite objects created in a thread can only be used in that same thread. The object was created in thread id 140517269673536 and this is thread id 140517035734592.
[SQL: SELECT playlist_entry_metadata.artificial_id AS playlist_entry_metadata_artificial_id, playlist_entry_metadata.artificial_entry_id AS playlist_entry_metadata_artificial_entry_id, playlist_entry_metadata.artist AS playlist_entry_metadata_artist, playlist_entry_metadata.title AS playlist_entry_metadata_title, playlist_entry_metadata.album AS playlist_entry_metadata_album
FROM playlist_entry_metadata
WHERE ? = playlist_entry_metadata.artificial_entry_id]
[parameters: [{'%(140517270128672 param)s': 4}]]
(Background on this error at: http://sqlalche.me/e/13/f405)