@@ -15,12 +15,122 @@ Transactions
15
15
Version 4.0 of the MongoDB server introduces
16
16
`multi-document transactions <https://mongodb.com/docs/manual/core/transactions/>`_.
17
17
(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.
20
22
21
23
Using Transactions
22
24
==================
23
25
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
+
24
134
In order to start a transaction, the application must have a :ref:`session <sessions>`.
25
135
26
136
A transaction can be started by calling the ``start_transaction`` method on a session, which can be
0 commit comments