Skip to content

Commit 537cf2e

Browse files
committed
edits
1 parent 243879f commit 537cf2e

File tree

3 files changed

+30
-42
lines changed

3 files changed

+30
-42
lines changed

django_mongodb_backend/base.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -161,15 +161,10 @@ def __init__(self, settings_dict, alias=DEFAULT_DB_ALIAS):
161161
self.session = None
162162

163163
# Transaction related attributes.
164-
# Tracks if the connection is in autocommit mode. Per PEP 249, by
165-
# default, it isn't.
166-
self.autocommit_mongo = False
167164
# Tracks if the connection is in a transaction managed by 'atomic'.
168165
self.in_atomic_block_mongo = False
169-
# Increment to generate unique savepoint ids.
170-
self.savepoint_state = 0
171-
# List of savepoints created by 'atomic'.
172-
self.savepoint_ids = []
166+
# Current number of nested 'atomic' calls.
167+
self.nested_atomics = 0
173168
# Stack of active 'atomic' blocks.
174169
self.atomic_blocks_mongo = []
175170
# Tracks if the outermost 'atomic' block should commit on exit,
@@ -277,6 +272,11 @@ def validate_no_broken_transaction(self):
277272
"execute queries until the end of the 'atomic' block."
278273
) from self.rollback_exc
279274

275+
def validate_no_atomic_block(self):
276+
"""Raise an error if an atomic block is active."""
277+
if self.in_atomic_block_mongo:
278+
raise TransactionManagementError("This is forbidden when an 'atomic' block is active.")
279+
280280
def get_database_version(self):
281281
"""Return a tuple of the database's version."""
282282
return tuple(self.connection.server_info()["versionArray"])
@@ -296,7 +296,7 @@ def _start_transaction(self, autocommit, force_begin_transaction_with_broken_aut
296296
self.session.start_transaction()
297297

298298
@requires_transaction_support
299-
def _commit_transaction(self):
299+
def commit_mongo(self):
300300
self.validate_thread_sharing()
301301
self.validate_no_atomic_block()
302302
if self.session:
@@ -309,7 +309,7 @@ def _commit_transaction(self):
309309

310310
@async_unsafe
311311
@requires_transaction_support
312-
def _rollback_transaction(self):
312+
def rollback_mongo(self):
313313
"""Roll back a MongoDB transaction and reset the dirty flag."""
314314
self.validate_thread_sharing()
315315
self.validate_no_atomic_block()
@@ -319,7 +319,7 @@ def _rollback_transaction(self):
319319
self._end_session()
320320
# A successful rollback means that the database connection works.
321321
self.errors_occurred = False
322-
self.needs_rollback = False
322+
self.needs_rollback_mongo = False
323323
self.run_on_commit = []
324324

325325
def _end_session(self):

django_mongodb_backend/transaction.py

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,12 @@ def __enter__(self):
6868
# Pretend we're already in an atomic block to bypass the code
6969
# that disables autocommit to enter a transaction, and make a
7070
# note to deal with this case in __exit__.
71-
connection.in_atomic_block_mongo = True
72-
connection.commit_on_exit = False
71+
# connection.in_atomic_block_mongo = True
72+
# connection.commit_on_exit = False
7373

7474
if connection.in_atomic_block_mongo:
75-
# We're already in a transaction
76-
pass
75+
# We're already in a transaction. Increment the number of nested atomics.
76+
connection.nested_atomics += 1
7777
else:
7878
connection._start_transaction(
7979
False, force_begin_transaction_with_broken_autocommit=True
@@ -89,25 +89,23 @@ def __exit__(self, exc_type, exc_value, traceback):
8989
if connection.in_atomic_block_mongo:
9090
connection.atomic_blocks_mongo.pop()
9191

92-
# Prematurely unset this flag to allow using commit or rollback.
93-
connection._in_atomic_block = False
92+
if connection.nested_atomics:
93+
connection.nested_atomics -= 1
94+
else:
95+
# Prematurely unset this flag to allow using commit or rollback.
96+
connection.in_atomic_block_mongo = False
9497
try:
95-
if connection.closed_in_transaction:
96-
# The database will perform a rollback by itself.
97-
# Wait until we exit the outermost block.
98-
pass
99-
100-
elif exc_type is None and not connection.needs_rollback_mongo:
101-
if connection._in_atomic_block:
98+
if exc_type is None and not connection.needs_rollback_mongo:
99+
if connection.in_atomic_block_mongo:
102100
# Release savepoint if there is one
103101
pass
104102
else:
105103
# Commit transaction
106104
try:
107-
connection._commit_transaction()
105+
connection.commit_mongo()
108106
except DatabaseError:
109107
try:
110-
connection._rollback_transaction()
108+
connection.rollback_mongo()
111109
except Error:
112110
# An error during rollback means that something
113111
# went wrong with the connection. Drop it.
@@ -123,24 +121,19 @@ def __exit__(self, exc_type, exc_value, traceback):
123121
else:
124122
# Roll back transaction
125123
try:
126-
connection._rollback_transaction()
124+
connection.rollback_mongo()
127125
except Error:
128126
# An error during rollback means that something
129127
# went wrong with the connection. Drop it.
130128
connection.close()
131129
finally:
132130
# Outermost block exit when autocommit was enabled.
133131
if not connection.in_atomic_block_mongo:
134-
if connection.closed_in_transaction:
135-
connection.connection = None
136-
# else:
137-
# connection.set_autocommit(True)
132+
pass
133+
# connection.set_autocommit(True)
138134
# Outermost block exit when autocommit was disabled.
139135
elif not connection.commit_on_exit:
140-
if connection.closed_in_transaction:
141-
connection.connection = None
142-
else:
143-
connection.in_atomic_block_mongo = False
136+
connection.in_atomic_block_mongo = False
144137

145138

146139
def atomic(using=None, durable=False):

tests/transactions_/tests.py

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import sys
2+
from unittest import expectedFailure
23

34
from django.db import Error, IntegrityError, connection
45
from django.test import TransactionTestCase, skipIfDBFeature, skipUnlessDBFeature
@@ -77,6 +78,7 @@ def test_nested_commit_commit(self):
7778
reporter2 = Reporter.objects.create(first_name="Archibald", last_name="Haddock")
7879
self.assertSequenceEqual(Reporter.objects.all(), [reporter2, reporter1])
7980

81+
@expectedFailure
8082
def test_nested_commit_rollback(self):
8183
with transaction.atomic():
8284
reporter = Reporter.objects.create(first_name="Tintin")
@@ -111,6 +113,7 @@ def test_reuse_commit_commit(self):
111113
reporter2 = Reporter.objects.create(first_name="Archibald", last_name="Haddock")
112114
self.assertSequenceEqual(Reporter.objects.all(), [reporter2, reporter1])
113115

116+
@expectedFailure
114117
def test_reuse_commit_rollback(self):
115118
atomic = transaction.atomic()
116119
with atomic:
@@ -140,14 +143,6 @@ def test_reuse_rollback_rollback(self):
140143
raise Exception("Oops, that's his first name")
141144
self.assertSequenceEqual(Reporter.objects.all(), [])
142145

143-
def test_force_rollback(self):
144-
with transaction.atomic():
145-
Reporter.objects.create(first_name="Tintin")
146-
# atomic block shouldn't rollback, but force it.
147-
self.assertFalse(transaction.get_rollback())
148-
transaction.set_rollback(True)
149-
self.assertSequenceEqual(Reporter.objects.all(), [])
150-
151146

152147
class AtomicInsideTransactionTests(AtomicTests):
153148
"""All basic tests for atomic should also pass within an existing transaction."""

0 commit comments

Comments
 (0)