You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In practice, nothing should go wrong until the application is handling multiple things at once (requests, scheduled jobs, ...), and since there are fairly few users and those users are unlikely to be working at the same time as the scheduled jobs (midnight UTC), it's unlikely this will actually cause any problems. However: if anything does go wrong because of this, it will be an absolute nightmare to work out what's happened.
Fixing this will probably involve using SQLAlchemy's scoped_session. One way would be to make the Database store a custom subclass of scoped_session instead of sessionmaker. The subclass would be very similar to SQLAlchemy's implementation, except it would use a new ContextVarsRegistry instead of SQLAlchemy's ScopedRegistry or ThreadLocalRegistry; this new registry would use Python 3.7's contextvars module (supported by aiohttp) to store one session per request. An aiohttp middleware to remove the session at the end of each request will also be necessary.
The text was updated successfully, but these errors were encountered:
To have one SQLAlchemy session per request, added two middlewares for creating and removing a session. The SQLAlchemy API does not require interacting with the session object directly; instead we use calls to Session class to indirectly call methods on session objects. The first time during the request cycle Session is called, it creates a new session object for the request context (supported by AIOHTTP) and saves it in ContextLocalRegistry using the contextvars module. Every subsequent call to Session in the request-context lifecycle uses this session object (obtained with a context.get() call)
Resolves: Issue #19
To have one SQLAlchemy session per request, added two middlewares for creating and removing a session. The SQLAlchemy API does not require interacting with the session object directly; instead we use calls to Session class to indirectly call methods on session objects. The first time during the request cycle Session is called, it creates a new session object for the request context (supported by AIOHTTP) and saves it in ContextLocalRegistry using the contextvars module. Every subsequent call to Session in the request-context lifecycle uses this session object (obtained with a context.get() call)
Resolves: Issue #19
Each
Database
uses exactly one SQLAlchemy session:backend/cogs/db/interface.py
Lines 53 to 54 in ca67e80
and the
Database
is shared across the whole application:backend/cogs/main.py
Line 64 in ca67e80
which implies that the entire application – all async contexts – shares a session.
This is terrible!
– from https://docs.sqlalchemy.org/en/13/orm/session_basics.html#is-the-session-thread-safe
In practice, nothing should go wrong until the application is handling multiple things at once (requests, scheduled jobs, ...), and since there are fairly few users and those users are unlikely to be working at the same time as the scheduled jobs (midnight UTC), it's unlikely this will actually cause any problems. However: if anything does go wrong because of this, it will be an absolute nightmare to work out what's happened.
Fixing this will probably involve using SQLAlchemy's
scoped_session
. One way would be to make the Database store a custom subclass ofscoped_session
instead ofsessionmaker
. The subclass would be very similar to SQLAlchemy's implementation, except it would use a newContextVarsRegistry
instead of SQLAlchemy'sScopedRegistry
orThreadLocalRegistry
; this new registry would use Python 3.7's contextvars module (supported by aiohttp) to store one session per request. An aiohttp middleware to remove the session at the end of each request will also be necessary.The text was updated successfully, but these errors were encountered: