mirror of
https://github.com/jlengrand/bugsink.git
synced 2026-03-10 08:01:17 +00:00
Support the combination (delay_on_commit, immediate_atomic, TASK_ALWAYS_EAGER)
As per the comment. Additionally, the original of _start_transaction_under_autocommit is stored on the contextprocessor now (which is the place with the best match of the actual call-stack anyway). (Was needed for nested invocations)
This commit is contained in:
@@ -8,6 +8,8 @@ import threading
|
||||
from django.db import transaction as django_db_transaction
|
||||
from django.db import DEFAULT_DB_ALIAS
|
||||
|
||||
from snappea.settings import get_settings as get_snappea_settings
|
||||
|
||||
performance_logger = logging.getLogger("bugsink.performance.db")
|
||||
local_storage = threading.local()
|
||||
|
||||
@@ -153,7 +155,7 @@ class ImmediateAtomic(SuperDurableAtomic):
|
||||
connection = django_db_transaction.get_connection(self.using)
|
||||
|
||||
if hasattr(connection, "_start_transaction_under_autocommit"):
|
||||
connection._start_transaction_under_autocommit_original = connection._start_transaction_under_autocommit
|
||||
self._start_transaction_under_autocommit_original = connection._start_transaction_under_autocommit
|
||||
connection._start_transaction_under_autocommit = types.MethodType(
|
||||
_start_transaction_under_autocommit_patched, connection)
|
||||
|
||||
@@ -183,9 +185,9 @@ class ImmediateAtomic(SuperDurableAtomic):
|
||||
performance_logger.info(f"{took * 1000:6.2f}ms IMMEDIATE transaction{using_clause}")
|
||||
|
||||
connection = django_db_transaction.get_connection(self.using)
|
||||
if hasattr(connection, "_start_transaction_under_autocommit"):
|
||||
connection._start_transaction_under_autocommit = connection._start_transaction_under_autocommit_original
|
||||
del connection._start_transaction_under_autocommit_original
|
||||
if hasattr(self, "_start_transaction_under_autocommit_original"):
|
||||
connection._start_transaction_under_autocommit = self._start_transaction_under_autocommit_original
|
||||
del self._start_transaction_under_autocommit_original
|
||||
|
||||
|
||||
@contextmanager
|
||||
@@ -206,10 +208,21 @@ def immediate_atomic(using=None, savepoint=True, durable=True):
|
||||
else:
|
||||
immediate_atomic = ImmediateAtomic(using, savepoint, durable)
|
||||
|
||||
# https://stackoverflow.com/a/45681273/339144 provides some context on nesting context managers; and how to proceed
|
||||
# if you want to do this with an arbitrary number of context managers.
|
||||
with SemaphoreContext(using), immediate_atomic:
|
||||
yield
|
||||
if get_snappea_settings().TASK_ALWAYS_EAGER:
|
||||
# In ALWAYS_EAGER mode we cannot use SemaphoreContext as the outermost context, because any delay_on_commit
|
||||
# tasks that are triggered on __exit__ of the (in that case, inner) immediate_atomic, when themselves initiating
|
||||
# a new task-with-transaction, will not be able to acquire the semaphore (it's not been released yet).
|
||||
# Fundamentally the solution would be to push the "on commit" logic onto the outermost context, but that seems
|
||||
# fragile (monkeypatching/heavy overriding) and since the whole SemaphoreContext is only needed as an extra
|
||||
# guard against WAL growth (not something we care about in the non-production setup), we just simplify for that
|
||||
# case.
|
||||
with immediate_atomic:
|
||||
yield
|
||||
else:
|
||||
# https://stackoverflow.com/a/45681273/339144 provides some context on nesting context managers; and how to
|
||||
# proceed if you want to do this with an arbitrary number of context managers.
|
||||
with SemaphoreContext(using), immediate_atomic:
|
||||
yield
|
||||
|
||||
|
||||
def delay_on_commit(function, *args, **kwargs):
|
||||
|
||||
Reference in New Issue
Block a user