Skip to content

Commit c430dee

Browse files
committed
MONGOID-4552 Implement transactions (#4507)
1 parent be376d4 commit c430dee

File tree

4 files changed

+497
-2
lines changed

4 files changed

+497
-2
lines changed

docs/tutorials/mongoid-sessions.txt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
.. _sessions:
2+
13
=========
24
Sessions
35
=========
@@ -35,7 +37,7 @@ of a session.
3537
.. code-block:: ruby
3638

3739
Person.with_session(causal_consistency: true) do
38-
Person.create
40+
Person.create!
3941
person = Person.first
4042
person.name = "Emily"
4143
person.save
@@ -53,5 +55,5 @@ of a session.
5355
person.with_session(causal_consistency: true) do
5456
person.username = 'Emily'
5557
person.save
56-
person.posts << Post.create
58+
person.posts << Post.create!
5759
end
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
============
2+
Transactions
3+
============
4+
5+
.. default-domain:: mongodb
6+
7+
.. contents:: On this page
8+
:local:
9+
:backlinks: none
10+
:depth: 1
11+
:class: singlecol
12+
13+
Version 4.0 of the MongoDB server introduces
14+
`multi-document transactions <https://docs.mongodb.com/manual/core/transactions/>`_.
15+
(Updates to multiple fields within a single document are atomic in all
16+
versions of MongoDB). Transactions require Mongoid version 6.4 or higher and Ruby driver version
17+
2.6 or higher.
18+
19+
Using Transactions
20+
------------------
21+
22+
In order to start a transaction, the application must have a :ref:`session <sessions>`.
23+
24+
A transaction can be started by calling the ``start_transaction`` method on a session, which can be
25+
obtained by calling the ``with_session`` method on either a model class or instance:
26+
27+
.. code-block:: ruby
28+
29+
class Person
30+
include Mongoid::Document
31+
end
32+
33+
Person.with_session do |session|
34+
session.start_transaction
35+
end
36+
37+
person = Person.new
38+
person.with_session do |session|
39+
session.start_transaction
40+
end
41+
42+
It is also possible to specify read concern, write concern and read preference
43+
when starting a transaction:
44+
45+
.. code-block:: ruby
46+
47+
Person.with_session do |session|
48+
session.start_transaction(
49+
read_concern: {level: :majority},
50+
write_concern: {w: 3},
51+
read: {mode: :primary})
52+
end
53+
54+
A transaction may be committed or aborted. The corresponding methods to do so are
55+
``commit_transaction`` and ``abort_transaction``, again on the session instance:
56+
57+
.. code-block:: ruby
58+
Person.with_session do |session|
59+
session.commit_transaction
60+
end
61+
62+
Person.with_session do |session|
63+
session.abort_transaction
64+
end
65+
66+
If a session ends with an open transaction,
67+
`the transaction is aborted <https://docs.mongodb.com/manual/core/transactions/#transactions-and-sessions>`_.
68+
69+
The transaction commit `can be retried <https://docs.mongodb.com/manual/core/transactions/#retry-commit-operation>`_
70+
if it fails. Here is the Ruby code to do so:
71+
72+
.. code-block:: ruby
73+
begin
74+
session.commit_transaction
75+
rescue Mongo::Error => e
76+
if e.label?(Mongo::Error::UNKNOWN_TRANSACTION_COMMIT_RESULT_LABEL)
77+
retry
78+
else
79+
raise
80+
end
81+
end
82+
83+
Note that in order to perform operations within the transaction, operations must use the same client
84+
that the session was initiated on. By default, all operations will be done on the default client:
85+
86+
.. code-block:: ruby
87+
class Person
88+
include Mongoid::Document
89+
end
90+
91+
class Post
92+
include Mongoid::Document
93+
end
94+
95+
Person.with_session do |s|
96+
s.start_transaction
97+
Person.create!
98+
Person.create!
99+
Post.create!
100+
s.commit_transaction
101+
end
102+
103+
To explicitly use a different client, use the ``with`` method:
104+
105+
.. code-block:: ruby
106+
Post.with(client: :other) do
107+
Person.with(client: :other) do
108+
Person.with_session do |s|
109+
s.start_transaction
110+
Person.create!
111+
Person.create!
112+
Post.create!
113+
s.commit_transaction
114+
end
115+
end
116+
end

0 commit comments

Comments
 (0)