@@ -25,32 +25,40 @@ In this guide, you can learn how to use {+odm+} to perform
2525that change data only if the entire transaction is committed.
2626If any operation in the transaction does not succeed, the driver stops the
2727transaction and discards all data changes before they ever become
28- visible. This feature is called ** atomicity** .
28+ visible. This feature is called :wikipedia:` atomicity <Atomicity_(database_systems)>` .
2929
3030In MongoDB, transactions run within logical **sessions**. A
3131session is a grouping of related read or write operations that you
3232want to run sequentially. Sessions enable causal consistency for a group
33- of operations and allow you to run operations in an **ACID-compliant**
33+ of operations, which means that all processes in your application agree on
34+ the order of causally-related operations.
35+
36+ Sessions allow you to run operations in an **ACID-compliant**
3437transaction that meets an expectation of atomicity, consistency,
3538isolation, and durability. MongoDB guarantees that the data involved in
3639your transaction operations remains consistent, even if the operations
3740encounter unexpected errors.
3841
39- In {+odm+}, you can perform transactions by using the following APIs:
42+ In {+odm+}, you can perform transactions by using either of the
43+ following APIs:
4044
41- - :ref:`mongoid-txn-high-level `: {+odm+} manages the life cycle of the
45+ - :ref:`mongoid-txn-convenient `: {+odm+} manages the life cycle of the
4246 transaction. You can use this API in {+odm+} v9.0 and later.
4347
44- - :ref:`mongoid-txn-low-level `: You must manage the life cycle of the
48+ - :ref:`mongoid-txn-core `: You must manage the life cycle of the
4549 transaction. You can use this API in {+odm+} v6.4 and later.
4650
4751The :ref:`mongoid-txn-session` section describes how to make changes to
4852your data from within a session without performing a transaction.
4953
50- .. _mongoid-txn-high-level:
54+ .. _mongoid-txn-convenient:
55+
56+ Convenient Transaction API
57+ --------------------------
5158
52- Higher Level API
53- ----------------
59+ You can use the Convenient Transaction API to internally manage the
60+ lifecycle of your transaction. This API either commits your transaction
61+ or ends it and incorporates error handling logic.
5462
5563You can start a transaction by calling the ``transaction()`` method on
5664an instance of a model, on the model class, or on a ``{+odm+}`` module.
@@ -65,15 +73,16 @@ following tasks:
6573#. Performs the specified data changes.
6674
6775#. Commits the transaction if no errors occur or ends the transaction if
68- there is an error. See the :ref:`` section to learn more an
76+ there is an error.
6977
7078#. Closes the session.
7179
7280If your transaction is committed, {+odm+} calls any ``after_commit``
7381callbacks for all objects modified inside the transaction. If there is
7482an error and the transaction is rolled back, {+odm+} calls any
7583``after_rollback`` callbacks for all objects modified inside the
76- transaction.
84+ transaction. To learn more about this behavior, see the
85+ :ref:`mongoid-txn-callbacks` section of this guide.
7786
7887Example
7988~~~~~~~
@@ -96,12 +105,12 @@ different objects to change data in multiple collections:
96105 :language: ruby
97106 :dedent:
98107
99- Client Limitations
100- ~~~~~~~~~~~~~~~~~~
108+ Client Behavior
109+ ~~~~~~~~~~~~~~~
101110
102- Only operations on the same client are in scope of a transaction,
111+ Only operations on the same client are in the scope of a transaction,
103112because each transaction is attached to a specific client. Ensure
104- that you use objects from same client inside the transaction method
113+ that you use objects from the same client inside the transaction method
105114block.
106115
107116The following example defines model classes that use different clients
@@ -122,10 +131,14 @@ Ending Transactions
122131~~~~~~~~~~~~~~~~~~~
123132
124133Any exception raised inside the transaction method block ends the
125- transaction and rolls back changes. Usually, {+odm+} displays the
126- exception, except for the ``Mongoid::Errors::Rollback`` exception. Implement
127- this exception in your application to explicitly end the transaction
128- without passing on an exception.
134+ transaction and rolls back data changes. {+odm+} displays all
135+ exceptions except for the ``Mongoid::Errors::Rollback`` exception. You
136+ must raise this exception in your application to explicitly end the
137+ transaction without returning the exception to you. You might implement
138+ this transaction exception to end a transaction when a certain condition
139+ is not met without raising an exception message.
140+
141+ .. _mongoid-txn-callbacks:
129142
130143Callbacks
131144~~~~~~~~~
@@ -143,21 +156,26 @@ created, saved, or deleted in the following cases:
143156 the transaction block.
144157
145158The ``after_commit`` callback is triggered only after all
146- other callbacks are executed successfully. Therefore, if an object is
147- modified without a transaction, it is possible that the object was
148- persisted, but the ``after_commit`` callback was not triggered, for
149- example, if {+odm+} raised an exception in the ``after_save`` callback.
159+ other callbacks are performed successfully. Therefore, if an object is
160+ modified outside of a transaction, it is possible that the object is then
161+ persisted, but the ``after_commit`` callback is not triggered. This
162+ might occur, for example, if {+odm+} raised an exception in the
163+ ``after_save`` callback because this callback must complete successfully
164+ to trigger ``after_commit``.
150165
151166The ``after_rollback`` callback is triggered for an object that was
152167created, saved, or deleted inside a transaction if the transaction was
153- ended. {+odm+} never triggers ``after_rollback`` outside of a transaction.
168+ ended. {+odm+} never triggers ``after_rollback`` outside of a
169+ transaction.
170+
171+ .. TODO link to callbacks guide.
154172
155- .. _mongoid-txn-low-level :
173+ .. _mongoid-txn-core :
156174
157- Lower Level API
158- ---------------
175+ Core Transaction API
176+ --------------------
159177
160- When using the lower level API, you must create a session before
178+ When using the Core API, you must create a session before
161179starting a transaction. You can create a session by calling the
162180``with_session()`` method on a model class or an instance of a model.
163181
@@ -182,6 +200,11 @@ preference when starting a transaction by passing options to the
182200 read: {mode: :primary}
183201 )
184202
203+ To learn more about the available transaction options, see
204+ `start_transaction()
205+ <{+ruby-api+}/Session.html#start_transaction-instance_method>`__ in the
206+ {+ruby-driver+} API documentation.
207+
185208When using this API, you must manually commit or end the transaction.
186209You can use the ``commit_transaction()`` and ``abort_transaction()``
187210methods on the session instance to manage the transaction lifecycle:
@@ -197,8 +220,9 @@ methods on the session instance to manage the transaction lifecycle:
197220 If a session ends and includes an open transaction, the transaction is
198221 automatically ended.
199222
200- You can retry the transaction commit if it fails,
201- as shown in the following code:
223+ You can retry the transaction commit if it fails initially. The
224+ following example demonstrates how to retry the transaction when {+odm+}
225+ raises the ``UNKNOWN_TRANSACTION_COMMIT_RESULT_LABEL`` exception:
202226
203227.. literalinclude:: /includes/interact-data/transaction.rb
204228 :start-after: start-commit-retry
@@ -223,8 +247,8 @@ To explicitly use a different client, use the ``with()`` method:
223247
224248.. _mongoid-txn-session:
225249
226- Perform Data Operations in a Session
227- ------------------------------------
250+ Session API
251+ -----------
228252
229253You can use sessions in {+odm+} in a similar way that you can
230254perform a transaction. You can call the ``with_session()`` method on a
@@ -236,37 +260,54 @@ The following limitations apply when using sessions:
236260
237261- You cannot share a session across threads. Sessions are not thread-safe.
238262
239- - You cannot nest sessions. You cannot call the ``with_session()``
240- method on a model class or a model instance within the block passed to
241- the ``with_session()`` method on another model class or model instance.
263+ - You cannot nest sessions. For example, you cannot call the ``with_session()``
264+ method on a model class within the block passed to
265+ the ``with_session()`` method on another model class. The following
266+ code demonstrates a nested session that results in an error:
267+
268+ .. code-block:: ruby
269+
270+ Book.with_session(causal_consistency: true) do
271+ # Nesting sessions results in errors
272+ Film.with_session(causal_consistency: true) do
273+ ...
274+ end
275+ end
242276
243277- All model classes and instances used within the session block must use
244278 the same driver client. For example, if you specify different
245- ``storage_options`` for another model used in the block than those of the
279+ a different client for a model used in the block than those of the
246280 model or instance that you called ``with_session()`` on, {+odm+} returns
247281 an error.
248282
249283Examples
250284~~~~~~~~
251285
252- You can use the ``with_session()`` on a model class and pass it session
286+ You can use the ``with_session()`` method on a model class and pass it session
253287options to perform a block of operations in the context of a session.
254288
255- The following code enables the ``causal_consistency`` option when
256- creating a session, then performs data operations:
289+ The following code enables the ``causal_consistency`` option to
290+ guarantee the order of operations when creating a session, then
291+ performs data operations:
257292
258293.. literalinclude:: /includes/interact-data/transaction.rb
259294 :start-after: start-model-session
260295 :end-before: end-model-session
261296 :language: ruby
262297 :dedent:
263298
299+ To learn more about the available session options, see the
300+ `Session class constructor details
301+ <{+ruby-api+}/Session.html#initialize-instance_method>`__ in the
302+ {+ruby-driver+} API documentation.
303+
264304Alternatively, you can use the ``with_session()`` on an instance of a
265305model and pass it session options to perform a block of operations in
266306the context of a session.
267307
268- The following code enables the ``causal_consistency`` option when
269- creating a session, then performs data operations:
308+ The following code enables the ``causal_consistency`` option to
309+ guarantee the order of operations when creating a session, then
310+ performs data operations:
270311
271312.. literalinclude:: /includes/interact-data/transaction.rb
272313 :start-after: start-instance-session
0 commit comments