The code in src/app/groups/services.py has a method which is called add_members. An error is thrown when the property group.members is accessed, because SQLalchemy probably tries to lazy-load the contents. Although I specified (using selectinload) that the property should be loaded at once, it still tries to do that and fails (probably because sqlite does not allow for lazy loading/parallel connections).
This is the exact error thrown:
Traceback (most recent call last):
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/litestar/middleware/_internal/exceptions/middleware.py", line 159, in call
await self.app(scope, receive, capture_response_started)
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/litestar/routes/http.py", line 80, in handle
response = await self._get_response_for_request(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/litestar/routes/http.py", line 132, in _get_response_for_request
return await self._call_handler_function(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/litestar/routes/http.py", line 152, in _call_handler_function
response_data, cleanup_group = await self._get_response_data(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/litestar/routes/http.py", line 192, in get_response_data
else await route_handler.fn(**parsed_kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/cq-manager/src/app/domain/groups/controllers.py", line 124, in add_members_handler
group, invite_task, message_task = await GroupService.add_members(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/cq-manager/src/app/domain/groups/services.py", line 110, in add_members
if group.members is None:
^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/orm/attributes.py", line 566, in get
return self.impl.get(state, dict) # type: ignore[no-any-return]
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/orm/attributes.py", line 1086, in get
value = self._fire_loader_callables(state, key, passive)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/orm/attributes.py", line 1121, in fire_loader_callables
return self.callable(state, passive)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/orm/strategies.py", line 978, in _load_for_state
return self._emit_lazyload(
^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/orm/strategies.py", line 1109, in _emit_lazyload
lazy_clause, params = self._generate_lazy_clause(state, passive)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/orm/strategies.py", line 858, in _generate_lazy_clause
value = mapper._get_state_attr_by_column(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/orm/mapper.py", line 3592, in get_state_attr_by_column
return state.manager[prop.key].impl.get(state, dict, passive=passive)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/orm/attributes.py", line 1086, in get
value = self._fire_loader_callables(state, key, passive)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/orm/attributes.py", line 1116, in _fire_loader_callables
return state._load_expired(state, passive)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/orm/state.py", line 803, in _load_expired
self.manager.expired_attribute_loader(self, toload, passive)
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/orm/loading.py", line 1670, in load_scalar_attributes
result = load_on_ident(
^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/orm/loading.py", line 509, in load_on_ident
return load_on_pk_identity(
^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/orm/loading.py", line 694, in load_on_pk_identity
session.execute(
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/orm/session.py", line 2362, in execute
return self._execute_internal(
^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/orm/session.py", line 2237, in _execute_internal
conn = self._connection_for_bind(bind)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/orm/session.py", line 2106, in _connection_for_bind
return trans._connection_for_bind(engine, execution_options)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "", line 2, in _connection_for_bind
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/orm/state_changes.py", line 139, in _go
ret_value = fn(self, *arg, **kw)
^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/orm/session.py", line 1189, in _connection_for_bind
conn = bind.connect()
^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 3278, in connect
return self._connection_cls(self)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 146, in init
self._dbapi_connection = engine.raw_connection()
^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 3302, in raw_connection
return self.pool.connect()
^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/pool/base.py", line 449, in connect
return _ConnectionFairy._checkout(self)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/pool/base.py", line 1263, in _checkout
fairy = _ConnectionRecord.checkout(pool)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/pool/base.py", line 712, in checkout
rec = pool._do_get()
^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/pool/impl.py", line 308, in _do_get
return self._create_connection()
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/pool/base.py", line 390, in _create_connection
return _ConnectionRecord(self)
^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/pool/base.py", line 674, in init
self.__connect()
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/pool/base.py", line 900, in __connect
with util.safe_reraise():
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/util/langhelpers.py", line 146, in exit
raise exc_value.with_traceback(exc_tb)
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/pool/base.py", line 896, in __connect
self.dbapi_connection = connection = pool._invoke_creator(self)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/engine/create.py", line 643, in connect
return dialect.connect(*cargs, **cparams)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/engine/default.py", line 621, in connect
return self.loaded_dbapi.connect(*cargs, **cparams)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 352, in connect
await_only(connection),
^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 123, in await_only
raise exc.MissingGreenlet(
sqlalchemy.exc.MissingGreenlet: greenlet_spawn has not been called; can't call await_only() here. Was IO attempted in an unexpected place? (Background on this error at: https://sqlalche.me/e/20/xd2s)
The code in
src/app/groups/services.pyhas a method which is calledadd_members. An error is thrown when the property group.members is accessed, because SQLalchemy probably tries to lazy-load the contents. Although I specified (using selectinload) that the property should be loaded at once, it still tries to do that and fails (probably because sqlite does not allow for lazy loading/parallel connections).This is the exact error thrown:
Traceback (most recent call last):
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/litestar/middleware/_internal/exceptions/middleware.py", line 159, in call
await self.app(scope, receive, capture_response_started)
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/litestar/routes/http.py", line 80, in handle
response = await self._get_response_for_request(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/litestar/routes/http.py", line 132, in _get_response_for_request
return await self._call_handler_function(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/litestar/routes/http.py", line 152, in _call_handler_function
response_data, cleanup_group = await self._get_response_data(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/litestar/routes/http.py", line 192, in get_response_data
else await route_handler.fn(**parsed_kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/cq-manager/src/app/domain/groups/controllers.py", line 124, in add_members_handler
group, invite_task, message_task = await GroupService.add_members(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/cq-manager/src/app/domain/groups/services.py", line 110, in add_members
if group.members is None:
^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/orm/attributes.py", line 566, in get
return self.impl.get(state, dict) # type: ignore[no-any-return]
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/orm/attributes.py", line 1086, in get
value = self._fire_loader_callables(state, key, passive)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/orm/attributes.py", line 1121, in fire_loader_callables
return self.callable(state, passive)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/orm/strategies.py", line 978, in _load_for_state
return self._emit_lazyload(
^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/orm/strategies.py", line 1109, in _emit_lazyload
lazy_clause, params = self._generate_lazy_clause(state, passive)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/orm/strategies.py", line 858, in _generate_lazy_clause
value = mapper._get_state_attr_by_column(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/orm/mapper.py", line 3592, in get_state_attr_by_column
return state.manager[prop.key].impl.get(state, dict, passive=passive)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/orm/attributes.py", line 1086, in get
value = self._fire_loader_callables(state, key, passive)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/orm/attributes.py", line 1116, in _fire_loader_callables
return state._load_expired(state, passive)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/orm/state.py", line 803, in _load_expired
self.manager.expired_attribute_loader(self, toload, passive)
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/orm/loading.py", line 1670, in load_scalar_attributes
result = load_on_ident(
^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/orm/loading.py", line 509, in load_on_ident
return load_on_pk_identity(
^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/orm/loading.py", line 694, in load_on_pk_identity
session.execute(
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/orm/session.py", line 2362, in execute
return self._execute_internal(
^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/orm/session.py", line 2237, in _execute_internal
conn = self._connection_for_bind(bind)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/orm/session.py", line 2106, in _connection_for_bind
return trans._connection_for_bind(engine, execution_options)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "", line 2, in _connection_for_bind
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/orm/state_changes.py", line 139, in _go
ret_value = fn(self, *arg, **kw)
^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/orm/session.py", line 1189, in _connection_for_bind
conn = bind.connect()
^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 3278, in connect
return self._connection_cls(self)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 146, in init
self._dbapi_connection = engine.raw_connection()
^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 3302, in raw_connection
return self.pool.connect()
^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/pool/base.py", line 449, in connect
return _ConnectionFairy._checkout(self)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/pool/base.py", line 1263, in _checkout
fairy = _ConnectionRecord.checkout(pool)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/pool/base.py", line 712, in checkout
rec = pool._do_get()
^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/pool/impl.py", line 308, in _do_get
return self._create_connection()
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/pool/base.py", line 390, in _create_connection
return _ConnectionRecord(self)
^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/pool/base.py", line 674, in init
self.__connect()
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/pool/base.py", line 900, in __connect
with util.safe_reraise():
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/util/langhelpers.py", line 146, in exit
raise exc_value.with_traceback(exc_tb)
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/pool/base.py", line 896, in __connect
self.dbapi_connection = connection = pool._invoke_creator(self)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/engine/create.py", line 643, in connect
return dialect.connect(*cargs, **cparams)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/engine/default.py", line 621, in connect
return self.loaded_dbapi.connect(*cargs, **cparams)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 352, in connect
await_only(connection),
^^^^^^^^^^^^^^^^^^^^^^
File "/home/frand/.virtualenvs/cq-manager/lib/python3.12/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 123, in await_only
raise exc.MissingGreenlet(
sqlalchemy.exc.MissingGreenlet: greenlet_spawn has not been called; can't call await_only() here. Was IO attempted in an unexpected place? (Background on this error at: https://sqlalche.me/e/20/xd2s)