@@ -5,7 +5,6 @@ module Clients
5
5
6
6
# Encapsulates behavior for using sessions and transactions.
7
7
module Sessions
8
-
9
8
def self . included ( base )
10
9
base . include ( ClassMethods )
11
10
end
@@ -46,8 +45,7 @@ def with_session(options = {})
46
45
end
47
46
rescue Mongo ::Error ::OperationFailure => ex
48
47
if ( ex . code == 40415 && ex . server_message =~ /startTransaction/ ) ||
49
- ( ex . code == 20 && ex . server_message =~ /Transaction/ )
50
- then
48
+ ( ex . code == 20 && ex . server_message =~ /Transaction/ )
51
49
raise Mongoid ::Errors ::TransactionsNotSupported . new
52
50
else
53
51
raise ex
@@ -82,27 +80,66 @@ def transaction(options = {}, session_options: {})
82
80
begin
83
81
session . start_transaction ( options )
84
82
yield
85
- session . commit_transaction
83
+ commit_transaction ( session )
86
84
rescue Mongoid ::Errors ::Rollback
87
- session . abort_transaction
85
+ abort_transaction ( session )
88
86
rescue Mongoid ::Errors ::InvalidSessionNesting
89
87
# Session should be ended here.
90
88
raise Mongoid ::Errors ::InvalidTransactionNesting . new
91
89
rescue Mongo ::Error ::InvalidSession , Mongo ::Error ::InvalidTransactionOperation => e
92
- session . abort_transaction
90
+ abort_transaction ( session )
93
91
raise Mongoid ::Errors ::TransactionError ( e )
94
92
rescue StandardError => e
95
- session . abort_transaction
93
+ abort_transaction ( session )
96
94
raise e
97
95
end
98
96
end
99
97
end
100
98
101
99
private
102
100
101
+ # @return [ Mongo::Session ] Session for the current client.
103
102
def _session
104
103
Threaded . get_session ( client : persistence_context . client )
105
104
end
105
+
106
+ # This method should be used to detect whether a persistence operation
107
+ # is executed inside transaction or not.
108
+ #
109
+ # Currently this method is used to detect when +after_commit+ callbacks
110
+ # should be triggered. If we introduce implicit transactions and
111
+ # therefore do not need to handle two different ways of triggering callbacks,
112
+ # we may want to remove this method.
113
+ #
114
+ # @return [ true | false ] Whether there is a session for the current
115
+ # client, and there is a transaction in progress for this session.
116
+ def in_transaction?
117
+ _session &.in_transaction? || false
118
+ end
119
+
120
+ # Commits the active transaction on the session, and calls
121
+ # after_commit callbacks on modified documents.
122
+ #
123
+ # @param [ Mongo::Session ] session Session on which
124
+ # a transaction is started.
125
+ def commit_transaction ( session )
126
+ session . commit_transaction
127
+ Threaded . clear_modified_documents ( session ) . each do |doc |
128
+ doc . run_after_callbacks ( :commit )
129
+ end
130
+ end
131
+
132
+ # Aborts the active transaction on the session, and calls
133
+ # after_rollback callbacks on modified documents.
134
+ #
135
+ # @param [ Mongo::Session ] session Session on which
136
+ # a transaction is started.
137
+ def abort_transaction ( session )
138
+ session . abort_transaction
139
+ Threaded . clear_modified_documents ( session ) . each do |doc |
140
+ doc . run_after_callbacks ( :rollback )
141
+ end
142
+ end
106
143
end
107
144
end
108
145
end
0 commit comments