@@ -15,12 +15,122 @@ Transactions
1515Version 4.0 of the MongoDB server introduces
1616`multi-document transactions <https://mongodb.com/docs/manual/core/transactions/>`_.
1717(Updates to multiple fields within a single document are atomic in all
18- versions of MongoDB). Transactions require Mongoid version 6.4 or higher and Ruby driver version
19- 2.6 or higher.
18+ versions of MongoDB). Transactions require a non-standalone MongoDB topology
19+ and Ruby driver version 2.6 or higher. A higher level transaction API requires
20+ Mongoid version 9.0 or higher, while a lower level API requires Mongoid
21+ version 6.4 or higher.
2022
2123Using Transactions
2224==================
2325
26+ Higher Level API
27+ ----------------
28+
29+ A transaction can be started by calling the ``transaction`` method on an instance
30+ of a Mongoid document class, on a Mongoid document class, on or ``Mongoid`` module:
31+
32+ .. code-block:: ruby
33+
34+ Band.transaction do
35+ Band.create(title: 'Led Zeppelin')
36+ end
37+
38+ band = Band.create(title: 'Deep Purple')
39+ band.transaction do
40+ band.active = false
41+ band.save!
42+ end
43+
44+ Mongoid.transaction do
45+ band.destroy
46+ end
47+
48+ When the ``transaction`` method is called, Mongoid does the following:
49+
50+ * creates a session on a client that is used by the receiver of the
51+ ``transaction`` method call;
52+ * starts a transaction on the session;
53+ * executes the given block;
54+ * commits the transaction if no exception raised in the block;
55+
56+ * calls ``after_commit`` callbacks for all objects modified inside the transaction
57+ * aborts the transaction if an exception is raised in the block;
58+
59+ * calls ``after_rollback`` callbacks for all objects modified inside the transaction
60+ * closes the session
61+
62+ .. note::
63+
64+ Since a transaction is tied to a particular client, _only_ operations on
65+ the same client will be in scope of the transaction. Therefore it
66+ is recommended that only objects that use the same client are used inside the
67+ ``transaction`` method block.
68+
69+ .. code-block:: ruby
70+
71+ class Author
72+ include Mongoid::Document
73+ store_in client: :encrypted_client
74+ end
75+
76+ class User
77+ include Mongoid::Document
78+ store_in client: :encrypted_client
79+ end
80+
81+ class Article
82+ include Mongoid::Document
83+ # This class uses the :default client
84+ end
85+
86+ # Transaction is started on the :encrypted_client
87+ Author.transaction do
88+ # This operation uses the same client, so it is in the transaction
89+ Author.create!
90+ # This operation also uses the same client, so it is in the transaction
91+ User.create!
92+ # This operation uses a different client, so it is NOT in the transaction
93+ Article.create!
94+ end
95+
96+ .. note::
97+ When ``transaction`` method is called on ``Mongoid`` module, the transaction
98+ is created using the ``:default`` client.
99+
100+ Aborting Transaction
101+ ~~~~~~~~~~~~~~~~~~~~
102+
103+ Any exception raised inside the ``transaction`` method block aborts the
104+ transaction. Normally the raised exception passed on, except for the
105+ ``Mongoid::Errors::Rollback``. This error should be raised if you want to
106+ explicitly abort the transaction without passing on an exception.
107+
108+ Callbacks
109+ ~~~~~~~~~
110+
111+ Transaction API introduces two new callbacks - ``after_commit`` and ``after_rollback``.
112+
113+ ``after_commit`` callback is triggered for an object that was created, saved,
114+ or destroyed:
115+
116+ * after transaction is committed if the object was modified inside the transaction;
117+ * after the object was persisted if the object was modified outside a transaction.
118+
119+ .. note::
120+ In any case ``after_commit`` callback is triggered only after all other callbacks
121+ were executed successfully. Therefore, if the object is modified without a
122+ transaction, it is possible that the object was persisted, but ``after_commit``
123+ callback was not triggered (for example, an exception raised in ``after_save``
124+ callback).
125+
126+ ``after_rollback`` callback is triggered for an object that was created, saved,
127+ or destroyed inside a transaction if the transaction was aborted. ``after_rollback``
128+ is never triggered without a transaction.
129+
130+
131+ Lower Level API
132+ ---------------
133+
24134In order to start a transaction, the application must have a :ref:`session <sessions>`.
25135
26136A transaction can be started by calling the ``start_transaction`` method on a session, which can be
0 commit comments