Skip to content

Commit 08b101a

Browse files
committed
doc edits
1 parent af29b2f commit 08b101a

File tree

3 files changed

+61
-76
lines changed

3 files changed

+61
-76
lines changed

django_mongodb_backend/base.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -285,14 +285,12 @@ def get_database_version(self):
285285
"""Return a tuple of the database's version."""
286286
return tuple(self.connection.server_info()["versionArray"])
287287

288-
@requires_transaction_support
289288
def _start_transaction(self):
290289
if self.session is None:
291290
self.session = self.connection.start_session()
292291
with debug_transaction(self, "session.start_transaction()"):
293292
self.session.start_transaction()
294293

295-
@requires_transaction_support
296294
def commit_mongo(self):
297295
self.validate_thread_sharing()
298296
self.validate_no_atomic_block()
@@ -305,7 +303,6 @@ def commit_mongo(self):
305303
self.run_commit_hooks_on_set_autocommit_on = True
306304

307305
@async_unsafe
308-
@requires_transaction_support
309306
def rollback_mongo(self):
310307
"""Roll back a MongoDB transaction and reset the dirty flag."""
311308
self.validate_thread_sharing()
@@ -331,8 +328,7 @@ def on_commit(self, func, robust=False):
331328
# Transaction in progress; save for execution on commit.
332329
self.run_on_commit.append((set(self.savepoint_ids), func, robust))
333330
else:
334-
# No transaction in progress and in autocommit mode; execute
335-
# immediately.
331+
# No transaction in progress; execute immediately.
336332
if robust:
337333
try:
338334
func()

docs/source/topics/known-issues.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,12 @@ Database functions
8080
Transaction management
8181
======================
8282

83-
Query execution uses Django and MongoDB's default behavior of autocommit mode.
84-
Each query is immediately committed to the database.
83+
By default, query execution uses Django and MongoDB's default behavior of autocommit
84+
mode. Each query is immediately committed to the database.
8585

8686
Django's :doc:`transaction management APIs <django:topics/db/transactions>`
8787
are not supported. Instead, this package provides its own :doc:`transaction APIs
88-
<topics/transactions>`.
88+
</topics/transactions>`.
8989

9090
Database introspection
9191
======================

docs/source/topics/transactions.rst

Lines changed: 57 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -4,100 +4,87 @@ Transactions
44

55
.. versionadded:: 5.2.0b2
66

7-
.. module:: django_mongod_backend.transaction
7+
.. module:: django_mongodb_backend.transaction
88

99
MongoDB supports :doc:`transactions <manual:core/transactions>` if it's configured as a
1010
:doc:`replica set <manual:replication>` or a :doc:`sharded cluster <manual:sharding>`.
1111

12-
Because MongoDB transactions have some differences compared to SQL transactions,
13-
:doc:`Django's transactions APIs <django:topics/db/transactions>` function as no-ops.
12+
Because MongoDB transactions have some limitations and are not meant to be used as
13+
freely as SQL transactions, :doc:`Django's transactions APIs
14+
<django:topics/db/transactions>`, including most notably
15+
:func:`django.db.transaction.atomic`, function as no-ops.
1416

15-
Instead, Django MongoDB Backend provides its own ``atomic()`` function, similar to
16-
Django's :func:`django.db.transaction.atomic`.
17+
Instead, Django MongoDB Backend provides its own
18+
:func:`django_mongodb_backend.transaction.atomic` function.
1719

1820
Outside of a transaction, query execution uses Django and MongoDB's default behavior of
1921
autocommit mode. Each query is immediately committed to the database.
2022

2123
Controlling transactions
22-
------------------------
24+
========================
2325

2426
.. function:: atomic(using=None, durable=False)
2527

26-
Atomicity is the defining property of database transactions. ``atomic``
27-
allows us to create a block of code within which the atomicity on the
28-
database is guaranteed. If the block of code is successfully completed, the
29-
changes are committed to the database. If there is an exception, the
30-
changes are rolled back.
28+
Atomicity is the defining property of database transactions. ``atomic`` allows
29+
creating a block of code within which the atomicity on the database is guaranteed.
30+
If the block of code is successfully completed, the changes are committed to the
31+
database. If there is an exception, the changes are rolled back.
3132

32-
``atomic`` blocks can be nested. In this case, when an inner block
33-
completes successfully, its effects can still be rolled back if an
34-
exception is raised in the outer block at a later point.
35-
36-
It is sometimes useful to ensure an ``atomic`` block is always the
37-
outermost ``atomic`` block, ensuring that any database changes are
38-
committed when the block is exited without errors. This is known as
39-
durability and can be achieved by setting ``durable=True``. If the
40-
``atomic`` block is nested within another it raises a ``RuntimeError``.
33+
On databases that support savepoints, ``atomic`` blocks can be nested, such that
34+
the outermost ``atomic`` starts a transaction and inner ``atomic``\s create
35+
savepoints. Since MongoDB doesn't support savepoints, inner ``atomic`` blocks
36+
don't have any effect. The transaction commits once the outermost ``atomic`` exits.
4137

4238
``atomic`` is usable both as a :py:term:`decorator`::
4339

44-
from django.db import transaction
40+
from django_mongodb_backend import transaction
4541

4642

47-
@transaction.atomic
43+
@atomic
4844
def viewfunc(request):
4945
# This code executes inside a transaction.
5046
do_stuff()
5147

5248
and as a :py:term:`context manager`::
5349

54-
from django.db import transaction
50+
from django_mongodb_backend import transaction
5551

5652

5753
def viewfunc(request):
5854
# This code executes in autocommit mode (Django's default).
5955
do_stuff()
6056

61-
with transaction.atomic():
57+
with atomic():
6258
# This code executes inside a transaction.
6359
do_more_stuff()
6460

6561
.. admonition:: Avoid catching exceptions inside ``atomic``!
6662

67-
When exiting an ``atomic`` block, Django looks at whether it's exited
68-
normally or with an exception to determine whether to commit or roll
69-
back. If you catch and handle exceptions inside an ``atomic`` block,
70-
you may hide from Django the fact that a problem has happened. This
71-
can result in unexpected behavior.
72-
73-
This is mostly a concern for :exc:`~django.db.DatabaseError` and its
74-
subclasses such as :exc:`~django.db.IntegrityError`. After such an
75-
error, the transaction is broken and Django will perform a rollback at
76-
the end of the ``atomic`` block. If you attempt to run database
77-
queries before the rollback happens, Django will raise a
78-
:class:`~django.db.transaction.TransactionManagementError`. You may
79-
also encounter this behavior when an ORM-related signal handler raises
63+
When exiting an ``atomic`` block, Django looks at whether it's exited normally
64+
or with an exception to determine whether to commit or roll back. If you catch
65+
and handle exceptions inside an ``atomic`` block, you may hide from Django the
66+
fact that a problem has happened. This can result in unexpected behavior.
67+
68+
This is mostly a concern for :exc:`~django.db.DatabaseError` and its subclasses
69+
such as :exc:`~django.db.IntegrityError`. After such an error, the transaction
70+
is broken and Django will perform a rollback at the end of the ``atomic``
71+
block. If you attempt to run database queries before the rollback happens,
72+
Django will raise a :class:`~django.db.transaction.TransactionManagementError`.
73+
You may also encounter this behavior when an ORM-related signal handler raises
8074
an exception.
8175

82-
The correct way to catch database errors is around an ``atomic`` block
83-
as shown above. If necessary, add an extra ``atomic`` block for this
84-
purpose. This pattern has another advantage: it delimits explicitly
85-
which operations will be rolled back if an exception occurs.
86-
87-
If you catch exceptions raised by raw SQL queries, Django's behavior
88-
is unspecified and database-dependent.
89-
9076
.. admonition:: You may need to manually revert app state when rolling back a transaction.
9177

92-
The values of a model's fields won't be reverted when a transaction
93-
rollback happens. This could lead to an inconsistent model state unless
94-
you manually restore the original field values.
78+
The values of a model's fields won't be reverted when a transaction rollback
79+
happens. This could lead to an inconsistent model state unless you manually
80+
restore the original field values.
9581

96-
For example, given ``MyModel`` with an ``active`` field, this snippet
97-
ensures that the ``if obj.active`` check at the end uses the correct
98-
value if updating ``active`` to ``True`` fails in the transaction::
82+
For example, given ``MyModel`` with an ``active`` field, this snippet ensures
83+
that the ``if obj.active`` check at the end uses the correct value if updating
84+
``active`` to ``True`` fails in the transaction::
9985

100-
from django.db import DatabaseError, transaction
86+
from django_mongodb_backend import transaction
87+
from django.db import DatabaseError
10188

10289
obj = MyModel(active=False)
10390
obj.active = True
@@ -110,37 +97,39 @@ Controlling transactions
11097
if obj.active:
11198
...
11299

113-
This also applies to any other mechanism that may hold app state, such
114-
as caching or global variables. For example, if the code proactively
115-
updates data in the cache after saving an object, it's recommended to
116-
use :ref:`transaction.on_commit() <performing-actions-after-commit>`
117-
instead, to defer cache alterations until the transaction is actually
118-
committed.
119-
120-
In order to guarantee atomicity, ``atomic`` disables some APIs. Attempting
121-
to commit, roll back, or change the autocommit state of the database
122-
connection within an ``atomic`` block will raise an exception.
100+
This also applies to any other mechanism that may hold app state, such as
101+
caching or global variables. For example, if the code proactively updates data
102+
in the cache after saving an object, it's recommended to use
103+
:ref:`transaction.on_commit() <performing-actions-after-commit>` instead, to
104+
defer cache alterations until the transaction is actually committed.
123105

124106
``atomic`` takes a ``using`` argument which should be the name of a
125107
database. If this argument isn't provided, Django uses the ``"default"``
126108
database.
127109

128110
Under the hood, Django's transaction management code:
129111

130-
- opens a transaction when entering the outermost ``atomic`` block;
112+
- opens a transaction when entering the outermost ``atomic`` block
131113
- commits or rolls back the transaction when exiting the outermost block.
132114

133115
.. admonition:: Performance considerations
134116

135-
Open transactions have a performance cost for your database server. To
136-
minimize this overhead, keep your transactions as short as possible. This
137-
is especially important if you're using :func:`atomic` in long-running
138-
processes, outside of Django's request / response cycle.
117+
Open transactions have a performance cost for your database server. To minimize
118+
this overhead, keep your transactions as short as possible. This is especially
119+
important if you're using :func:`atomic` in long-running processes, outside of
120+
Django's request / response cycle.
121+
122+
Performing actions after commit
123+
===============================
124+
125+
The :func:`atomic` function supports Django's :func:`~django.db.transaction.on_commit`
126+
API to :ref:`perform actions after a transaction successfully commits
127+
<performing-actions-after-commit>`.
139128

140129
.. _transactions-limitations:
141130

142131
Limitations
143-
-----------
132+
===========
144133

145134
MongoDB's transaction limitations that are applicable to Django are:
146135

0 commit comments

Comments
 (0)