summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBarthelemy Dagenais <barthelemy@infobart.com>2016-05-17 10:54:57 -0400
committerTim Graham <timograham@gmail.com>2016-05-18 09:13:21 -0400
commit47da073cb01f86f6f71cf19a2866f80a9755f434 (patch)
treef5b76533d7999945835a55065b0c323414047c3c
parentff1eb0a6deeab6b07f30f11b2a6565ae9ec5556b (diff)
[1.9.x] Fixed #26627 -- Fixed on_commit callbacks execution order when callbacks make transactions.
Backport of a5c8072ab1e56da368a40f3e9c9a3b465f4ffbae from master
-rw-r--r--django/db/backends/base/base.py11
-rw-r--r--docs/releases/1.9.7.txt3
-rw-r--r--tests/transaction_hooks/tests.py14
3 files changed, 22 insertions, 6 deletions
diff --git a/django/db/backends/base/base.py b/django/db/backends/base/base.py
index 0356ab54cc..021fe0bafa 100644
--- a/django/db/backends/base/base.py
+++ b/django/db/backends/base/base.py
@@ -617,12 +617,11 @@ class BaseDatabaseWrapper(object):
def run_and_clear_commit_hooks(self):
self.validate_no_atomic_block()
- try:
- while self.run_on_commit:
- sids, func = self.run_on_commit.pop(0)
- func()
- finally:
- self.run_on_commit = []
+ current_run_on_commit = self.run_on_commit
+ self.run_on_commit = []
+ while current_run_on_commit:
+ sids, func = current_run_on_commit.pop(0)
+ func()
def copy(self, alias=None, allow_thread_sharing=None):
"""
diff --git a/docs/releases/1.9.7.txt b/docs/releases/1.9.7.txt
index 5514222888..2f5555721f 100644
--- a/docs/releases/1.9.7.txt
+++ b/docs/releases/1.9.7.txt
@@ -17,3 +17,6 @@ Bugfixes
* Fixed a regression causing the cached template loader to crash when using
lazy template names (:ticket:`26603`).
+
+* Fixed ``on_commit`` callbacks execution order when callbacks make
+ transactions (:ticket:`26627`).
diff --git a/tests/transaction_hooks/tests.py b/tests/transaction_hooks/tests.py
index ebf07bc656..000de4104c 100644
--- a/tests/transaction_hooks/tests.py
+++ b/tests/transaction_hooks/tests.py
@@ -208,6 +208,20 @@ class TestConnectionOnCommit(TransactionTestCase):
self.assertDone([1])
+ def test_hook_in_hook(self):
+ def on_commit(i, add_hook):
+ with transaction.atomic():
+ if add_hook:
+ transaction.on_commit(lambda: on_commit(i + 10, False))
+ t = Thing.objects.create(num=i)
+ self.notify(t.num)
+
+ with transaction.atomic():
+ transaction.on_commit(lambda: on_commit(1, True))
+ transaction.on_commit(lambda: on_commit(2, True))
+
+ self.assertDone([1, 11, 2, 12])
+
def test_raises_exception_non_autocommit_mode(self):
def should_never_be_called():
raise AssertionError('this function should never be called')