mirror of https://github.com/zulip/zulip.git
session: Enforce that changes cannot happen in a transaction.
This commit is contained in:
parent
b70a071124
commit
7650b5a972
|
@ -140,6 +140,8 @@ not_yet_fully_covered = [
|
||||||
"zerver/webhooks/teamcity/view.py",
|
"zerver/webhooks/teamcity/view.py",
|
||||||
"zerver/webhooks/travis/view.py",
|
"zerver/webhooks/travis/view.py",
|
||||||
"zerver/webhooks/zapier/view.py",
|
"zerver/webhooks/zapier/view.py",
|
||||||
|
# Cannot have coverage, as tests run in a transaction
|
||||||
|
"zerver/lib/safe_session_cached_db.py",
|
||||||
]
|
]
|
||||||
|
|
||||||
enforce_fully_covered = sorted(
|
enforce_fully_covered = sorted(
|
||||||
|
|
|
@ -56,7 +56,7 @@ def huddle_cache_items(items_for_remote_cache: Dict[str, Tuple[Huddle]], huddle:
|
||||||
|
|
||||||
|
|
||||||
def session_cache_items(items_for_remote_cache: Dict[str, str], session: Session) -> None:
|
def session_cache_items(items_for_remote_cache: Dict[str, str], session: Session) -> None:
|
||||||
if settings.SESSION_ENGINE != "django.contrib.sessions.backends.cached_db":
|
if settings.SESSION_ENGINE != "zerver.lib.safe_session_cached_db":
|
||||||
# If we're not using the cached_db session engine, we there
|
# If we're not using the cached_db session engine, we there
|
||||||
# will be no store.cache_key attribute, and in any case we
|
# will be no store.cache_key attribute, and in any case we
|
||||||
# don't need to fill the cache, since it won't exist.
|
# don't need to fill the cache, since it won't exist.
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from django.contrib.sessions.backends.cached_db import SessionStore as CachedDbSessionStore
|
||||||
|
from django.db.transaction import get_connection
|
||||||
|
|
||||||
|
|
||||||
|
class SessionStore(CachedDbSessionStore):
|
||||||
|
"""Caching session object which does not leak into the cache.
|
||||||
|
|
||||||
|
django.contrib.sessions.backends.cached_db does write-through to
|
||||||
|
the cache and the backing database. If the database is in a
|
||||||
|
transaction, this may leak not-yet-committed changes to the cache,
|
||||||
|
which can lead to inconsistent state. This class wraps changes to
|
||||||
|
the session in assertions which enforce that the database cannot
|
||||||
|
be in a transaction before writing.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
def save(self, must_create: bool = False) -> None:
|
||||||
|
assert not get_connection().in_atomic_block
|
||||||
|
super().save(must_create)
|
||||||
|
|
||||||
|
def delete(self, session_key: Optional[str] = None) -> None:
|
||||||
|
assert not get_connection().in_atomic_block
|
||||||
|
super().delete(session_key)
|
|
@ -334,7 +334,7 @@ RABBITMQ_PASSWORD = get_secret("rabbitmq_password")
|
||||||
# CACHING CONFIGURATION
|
# CACHING CONFIGURATION
|
||||||
########################################################################
|
########################################################################
|
||||||
|
|
||||||
SESSION_ENGINE = "django.contrib.sessions.backends.cached_db"
|
SESSION_ENGINE = "zerver.lib.safe_session_cached_db"
|
||||||
|
|
||||||
MEMCACHED_PASSWORD = get_secret("memcached_password")
|
MEMCACHED_PASSWORD = get_secret("memcached_password")
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue