mongo 2.6.0 → 2.6.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +3 -1
- data/lib/mongo.rb +1 -0
- data/lib/mongo/address.rb +1 -1
- data/lib/mongo/address/ipv4.rb +1 -1
- data/lib/mongo/address/ipv6.rb +1 -1
- data/lib/mongo/address/unix.rb +1 -1
- data/lib/mongo/client.rb +14 -7
- data/lib/mongo/collection/view/builder/op_query.rb +9 -1
- data/lib/mongo/collection/view/readable.rb +7 -2
- data/lib/mongo/database.rb +2 -1
- data/lib/mongo/error.rb +1 -0
- data/lib/mongo/error/lint_error.rb +35 -0
- data/lib/mongo/lint.rb +45 -0
- data/lib/mongo/operation/shared/read_preference_supported.rb +2 -1
- data/lib/mongo/operation/shared/sessions_supported.rb +5 -7
- data/lib/mongo/protocol/query.rb +1 -0
- data/lib/mongo/server.rb +1 -1
- data/lib/mongo/server/connection_pool.rb +5 -5
- data/lib/mongo/server/connection_pool/queue.rb +4 -4
- data/lib/mongo/server_selector.rb +1 -0
- data/lib/mongo/session.rb +48 -17
- data/lib/mongo/socket.rb +67 -7
- data/lib/mongo/socket/ssl.rb +6 -0
- data/lib/mongo/version.rb +1 -1
- data/spec/mongo/lint_spec.rb +152 -0
- data/spec/mongo/logger_spec.rb +1 -1
- data/spec/mongo/socket/ssl_spec.rb +1 -1
- data/spec/mongo/socket_spec.rb +42 -0
- metadata +408 -402
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d8e500892649b1d8d1817ec229c1d56d97837e252452654af04e995d1416082a
|
4
|
+
data.tar.gz: 5fa8c7ca6caa84c0c81ed9f8ab3cd6566f579fc10ac28f510628f2de790040c7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 725de14593b44d0bf8b370f53a5e18a8f5d033efddd2e05096ec561b69f51b01b70394d3c8ebab1e89dbb7ecbb7784dbb161376d1194130ae6d016afd39344ae
|
7
|
+
data.tar.gz: 989ee85302acac376637d777e1c83cff4e7fa5d932fc62d489b3192d0b7336875fe831a0742d9953892108d2cb86c5b825f84d73a1779c0149fef2ffbb04aa05
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
@@ -1 +1,3 @@
|
|
1
|
-
|
1
|
+
���6Ș�����>in{��M�(����Jʐ4���E�tm}W�BA8�������y��z���W�S��^<~6���&%q�`��M��(����<�7��Kݰxj�����d�\����f���f�f��EML�|3�tK�DЂ9�J<3-�,���<�Q��!E�g>L>��8Yf95��֙<i��l�gu������m�x[=�f�
|
2
|
+
��;�|klr��n
|
3
|
+
v�a����gn���0�O�I�S���r�PowVo`�
|
data/lib/mongo.rb
CHANGED
data/lib/mongo/address.rb
CHANGED
@@ -142,7 +142,7 @@ module Mongo
|
|
142
142
|
# @param [ Float ] socket_timeout The socket timeout.
|
143
143
|
# @param [ Hash ] ssl_options SSL options.
|
144
144
|
#
|
145
|
-
# @return [
|
145
|
+
# @return [ Mongo::Socket::SSL, Mongo::Socket::TCP, Mongo::Socket::Unix ] The socket.
|
146
146
|
#
|
147
147
|
# @since 2.0.0
|
148
148
|
def socket(socket_timeout, ssl_options = {})
|
data/lib/mongo/address/ipv4.rb
CHANGED
@@ -80,7 +80,7 @@ module Mongo
|
|
80
80
|
# @param [ Float ] socket_timeout The socket timeout.
|
81
81
|
# @param [ Hash ] ssl_options SSL options.
|
82
82
|
#
|
83
|
-
# @return [
|
83
|
+
# @return [ Mongo::Socket::SSL, Mongo::Socket::TCP ] The socket.
|
84
84
|
#
|
85
85
|
# @since 2.0.0
|
86
86
|
def socket(socket_timeout, ssl_options = {})
|
data/lib/mongo/address/ipv6.rb
CHANGED
@@ -96,7 +96,7 @@ module Mongo
|
|
96
96
|
# @param [ Float ] socket_timeout The socket timeout.
|
97
97
|
# @param [ Hash ] ssl_options SSL options.
|
98
98
|
#
|
99
|
-
# @return [
|
99
|
+
# @return [ Mongo::Socket::SSL, Mongo::Socket::TCP ] The socket.
|
100
100
|
#
|
101
101
|
# @since 2.0.0
|
102
102
|
def socket(socket_timeout, ssl_options = {})
|
data/lib/mongo/address/unix.rb
CHANGED
@@ -65,7 +65,7 @@ module Mongo
|
|
65
65
|
# @param [ Float ] socket_timeout The socket timeout.
|
66
66
|
# @param [ Hash ] ssl_options SSL options - ignored.
|
67
67
|
#
|
68
|
-
# @return [
|
68
|
+
# @return [ Mongo::Socket::Unix ] The socket.
|
69
69
|
#
|
70
70
|
# @since 2.0.0
|
71
71
|
def socket(socket_timeout, ssl_options = {})
|
data/lib/mongo/client.rb
CHANGED
@@ -193,7 +193,7 @@ module Mongo
|
|
193
193
|
# supports 'zlib'.
|
194
194
|
# @option options [ Hash ] :read The read preference options. The hash
|
195
195
|
# may have the following items:
|
196
|
-
# - *:
|
196
|
+
# - *:mode* -- read preference specified as a symbol; valid values are
|
197
197
|
# *:primary*, *:primary_preferred*, *:secondary*, *:secondary_preferred*
|
198
198
|
# and *:nearest*.
|
199
199
|
# - *:tag_sets* -- an array of hashes.
|
@@ -219,18 +219,18 @@ module Mongo
|
|
219
219
|
# @option options [ OpenSSL::PKey ] :ssl_key_object The private key used to identify the
|
220
220
|
# connection against MongoDB
|
221
221
|
# @option options [ String ] :ssl_key_pass_phrase A passphrase for the private key.
|
222
|
-
# @option options [ true, false ] :ssl_verify Whether
|
222
|
+
# @option options [ true, false ] :ssl_verify Whether to do peer certificate
|
223
223
|
# validation.
|
224
|
-
# @option options [ String ] :ssl_ca_cert The file containing
|
225
|
-
#
|
224
|
+
# @option options [ String ] :ssl_ca_cert The file containing concatenated
|
225
|
+
# certificate authority certificates used to validate certs passed from the
|
226
226
|
# other end of the connection. One of :ssl_ca_cert, :ssl_ca_cert_string or
|
227
227
|
# :ssl_ca_cert_object (in order of priority) is required for :ssl_verify.
|
228
|
-
# @option options [ String ] :ssl_ca_cert_string A string containing
|
229
|
-
#
|
228
|
+
# @option options [ String ] :ssl_ca_cert_string A string containing concatenated
|
229
|
+
# certificate authority certificates used to validate certs passed from the
|
230
230
|
# other end of the connection. One of :ssl_ca_cert, :ssl_ca_cert_string or
|
231
231
|
# :ssl_ca_cert_object (in order of priority) is required for :ssl_verify.
|
232
232
|
# @option options [ Array<OpenSSL::X509::Certificate> ] :ssl_ca_cert_object An array of
|
233
|
-
# OpenSSL::X509::Certificate representing the
|
233
|
+
# OpenSSL::X509::Certificate representing the certificate authority certificates used
|
234
234
|
# to validate certs passed from the other end of the connection. One of :ssl_ca_cert,
|
235
235
|
# :ssl_ca_cert_string or :ssl_ca_cert_object (in order of priority) is required for :ssl_verify.
|
236
236
|
# @option options [ Float ] :socket_timeout The timeout, in seconds, to
|
@@ -261,6 +261,7 @@ module Mongo
|
|
261
261
|
#
|
262
262
|
# @since 2.0.0
|
263
263
|
def initialize(addresses_or_uri, options = Options::Redacted.new)
|
264
|
+
Mongo::Lint.validate_underscore_read_preference(options[:read])
|
264
265
|
if addresses_or_uri.is_a?(::String)
|
265
266
|
create_from_uri(addresses_or_uri, validate_options!(options))
|
266
267
|
else
|
@@ -301,6 +302,12 @@ module Mongo
|
|
301
302
|
# client.read_preference
|
302
303
|
#
|
303
304
|
# @return [ BSON::Document ] The user-defined read preference.
|
305
|
+
# The document may have the following fields:
|
306
|
+
# - *:read* -- read preference specified as a symbol; valid values are
|
307
|
+
# *:primary*, *:primary_preferred*, *:secondary*, *:secondary_preferred*
|
308
|
+
# and *:nearest*.
|
309
|
+
# - *:tag_sets* -- an array of hashes.
|
310
|
+
# - *:local_threshold*.
|
304
311
|
#
|
305
312
|
# @since 2.0.0
|
306
313
|
def read_preference
|
@@ -68,7 +68,15 @@ module Mongo
|
|
68
68
|
end
|
69
69
|
|
70
70
|
def read_pref_formatted
|
71
|
-
@read_formatted ||=
|
71
|
+
@read_formatted ||= begin
|
72
|
+
if read
|
73
|
+
read_pref = ServerSelector.get(read).to_mongos
|
74
|
+
Mongo::Lint.validate_camel_case_read_preference(read_pref)
|
75
|
+
read_pref
|
76
|
+
else
|
77
|
+
nil
|
78
|
+
end
|
79
|
+
end
|
72
80
|
end
|
73
81
|
|
74
82
|
def special_filter
|
@@ -139,6 +139,7 @@ module Mongo
|
|
139
139
|
cmd[:limit] = opts[:limit] if opts[:limit]
|
140
140
|
cmd[:maxTimeMS] = opts[:max_time_ms] if opts[:max_time_ms]
|
141
141
|
cmd[:readConcern] = collection.read_concern if collection.read_concern
|
142
|
+
Mongo::Lint.validate_underscore_read_preference(opts[:read])
|
142
143
|
read_pref = opts[:read] || read_preference
|
143
144
|
selector = ServerSelector.get(read_pref || server_selector)
|
144
145
|
with_session(opts) do |session|
|
@@ -203,6 +204,7 @@ module Mongo
|
|
203
204
|
cmd = { count: collection.name }
|
204
205
|
cmd[:maxTimeMS] = opts[:max_time_ms] if opts[:max_time_ms]
|
205
206
|
cmd[:readConcern] = collection.read_concern if collection.read_concern
|
207
|
+
Mongo::Lint.validate_underscore_read_preference(opts[:read])
|
206
208
|
read_pref = opts[:read] || read_preference
|
207
209
|
selector = ServerSelector.get(read_pref || server_selector)
|
208
210
|
with_session(opts) do |session|
|
@@ -240,6 +242,7 @@ module Mongo
|
|
240
242
|
:query => filter }
|
241
243
|
cmd[:maxTimeMS] = opts[:max_time_ms] if opts[:max_time_ms]
|
242
244
|
cmd[:readConcern] = collection.read_concern if collection.read_concern
|
245
|
+
Mongo::Lint.validate_underscore_read_preference(opts[:read])
|
243
246
|
read_pref = opts[:read] || read_preference
|
244
247
|
selector = ServerSelector.get(read_pref || server_selector)
|
245
248
|
with_session(opts) do |session|
|
@@ -537,11 +540,13 @@ module Mongo
|
|
537
540
|
end
|
538
541
|
|
539
542
|
def read_preference
|
540
|
-
if options[:session] && options[:session].in_transaction?
|
541
|
-
options[:session].
|
543
|
+
rp = if options[:session] && options[:session].in_transaction?
|
544
|
+
options[:session].txn_read_preference || collection.client.read_preference
|
542
545
|
else
|
543
546
|
@read_preference ||= (options[:read] || collection.read_preference)
|
544
547
|
end
|
548
|
+
Mongo::Lint.validate_underscore_read_preference(rp)
|
549
|
+
rp
|
545
550
|
end
|
546
551
|
|
547
552
|
def server_selector
|
data/lib/mongo/database.rb
CHANGED
@@ -153,7 +153,8 @@ module Mongo
|
|
153
153
|
#
|
154
154
|
# @return [ Hash ] The result of the command execution.
|
155
155
|
def command(operation, opts = {})
|
156
|
-
txn_read_pref = opts[:session] && opts[:session].in_transaction? && opts[:session].
|
156
|
+
txn_read_pref = opts[:session] && opts[:session].in_transaction? && opts[:session].txn_read_preference
|
157
|
+
Mongo::Lint.validate_underscore_read_preference(txn_read_pref)
|
157
158
|
preference = ServerSelector.get(txn_read_pref || opts[:read] || ServerSelector::PRIMARY)
|
158
159
|
server = preference.select_server(cluster)
|
159
160
|
|
data/lib/mongo/error.rb
CHANGED
@@ -151,6 +151,7 @@ require 'mongo/error/invalid_update_document'
|
|
151
151
|
require 'mongo/error/invalid_uri'
|
152
152
|
require 'mongo/error/invalid_write_concern'
|
153
153
|
require 'mongo/error/insufficient_iteration_count'
|
154
|
+
require 'mongo/error/lint_error'
|
154
155
|
require 'mongo/error/max_bson_size'
|
155
156
|
require 'mongo/error/max_message_size'
|
156
157
|
require 'mongo/error/mismatched_domain'
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# Copyright (C) 2018 MongoDB, Inc.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
module Mongo
|
16
|
+
class Error
|
17
|
+
|
18
|
+
# Raised when the driver is used incorrectly.
|
19
|
+
#
|
20
|
+
# Normally the driver passes certain data to the server and lets the
|
21
|
+
# server return an error if the data is invalid. This makes it possible
|
22
|
+
# for the server to add functionality in the future and for older
|
23
|
+
# driver versions to support such functionality transparently, but
|
24
|
+
# also complicates debugging.
|
25
|
+
#
|
26
|
+
# Setting the environment variable MONGO_RUBY_DRIVER_LINT to 1, true
|
27
|
+
# or yes will make the driver perform additional checks on data it passes
|
28
|
+
# to the server, to flag failures sooner. This exception is raised on
|
29
|
+
# such failures.
|
30
|
+
#
|
31
|
+
# @since 2.7.0
|
32
|
+
class LintError < Error
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/mongo/lint.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
module Mongo
|
2
|
+
# @api private
|
3
|
+
module Lint
|
4
|
+
def validate_underscore_read_preference(read_pref)
|
5
|
+
return unless enabled?
|
6
|
+
if read_pref
|
7
|
+
validate_underscore_read_preference_mode(read_pref[:mode] || read_pref['mode'])
|
8
|
+
end
|
9
|
+
end
|
10
|
+
module_function :validate_underscore_read_preference
|
11
|
+
|
12
|
+
def validate_underscore_read_preference_mode(mode)
|
13
|
+
return unless enabled?
|
14
|
+
if mode
|
15
|
+
unless %w(primary primary_preferred secondary secondary_preferred nearest).include?(mode.to_s)
|
16
|
+
raise Error::LintError, "Invalid read preference mode: #{mode}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
module_function :validate_underscore_read_preference_mode
|
21
|
+
|
22
|
+
def validate_camel_case_read_preference(read_pref)
|
23
|
+
return unless enabled?
|
24
|
+
if read_pref
|
25
|
+
validate_camel_case_read_preference_mode(read_pref[:mode] || read_pref['mode'])
|
26
|
+
end
|
27
|
+
end
|
28
|
+
module_function :validate_camel_case_read_preference
|
29
|
+
|
30
|
+
def validate_camel_case_read_preference_mode(mode)
|
31
|
+
return unless enabled?
|
32
|
+
if mode
|
33
|
+
unless %w(primary primaryPreferred secondary secondaryPreferred nearest).include?(mode.to_s)
|
34
|
+
raise Error::LintError, "Invalid read preference mode: #{mode}"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
module_function :validate_camel_case_read_preference_mode
|
39
|
+
|
40
|
+
def enabled?
|
41
|
+
ENV['MONGO_RUBY_DRIVER_LINT'] && %w(1 yes true).include?(ENV['MONGO_RUBY_DRIVER_LINT'].downcase)
|
42
|
+
end
|
43
|
+
module_function :enabled?
|
44
|
+
end
|
45
|
+
end
|
@@ -30,8 +30,9 @@ module Mongo
|
|
30
30
|
|
31
31
|
def update_selector_for_read_pref(sel, server)
|
32
32
|
if read && server.mongos? && read_pref = read.to_mongos
|
33
|
+
Mongo::Lint.validate_camel_case_read_preference(read_pref)
|
33
34
|
sel = sel[:$query] ? sel : {:$query => sel}
|
34
|
-
sel.merge(:$readPreference => read_pref)
|
35
|
+
sel = sel.merge(:$readPreference => read_pref)
|
35
36
|
else
|
36
37
|
sel
|
37
38
|
end
|
@@ -24,8 +24,6 @@ module Mongo
|
|
24
24
|
|
25
25
|
ZERO_TIMESTAMP = BSON::Timestamp.new(0, 0)
|
26
26
|
|
27
|
-
READ_PREFERENCE = '$readPreference'.freeze
|
28
|
-
|
29
27
|
READ_COMMANDS = [
|
30
28
|
:aggregate,
|
31
29
|
:collStats,
|
@@ -101,8 +99,8 @@ module Mongo
|
|
101
99
|
session.suppress_read_write_concern!(selector)
|
102
100
|
end
|
103
101
|
|
104
|
-
def
|
105
|
-
session.
|
102
|
+
def validate_read_preference!(selector)
|
103
|
+
session.validate_read_preference!(selector) if read_command?(selector)
|
106
104
|
end
|
107
105
|
|
108
106
|
def update_session_state!
|
@@ -113,7 +111,7 @@ module Mongo
|
|
113
111
|
sel = selector(server)
|
114
112
|
add_write_concern!(sel)
|
115
113
|
sel[Protocol::Msg::DATABASE_IDENTIFIER] = db_name
|
116
|
-
sel[
|
114
|
+
sel['$readPreference'] = read.to_doc if read
|
117
115
|
|
118
116
|
if server.features.sessions_enabled?
|
119
117
|
apply_cluster_time!(sel, server)
|
@@ -125,7 +123,7 @@ module Mongo
|
|
125
123
|
apply_autocommit!(sel)
|
126
124
|
apply_txn_opts!(sel)
|
127
125
|
suppress_read_write_concern!(sel)
|
128
|
-
|
126
|
+
validate_read_preference!(sel)
|
129
127
|
update_session_state!
|
130
128
|
apply_txn_num!(sel)
|
131
129
|
end
|
@@ -138,7 +136,7 @@ module Mongo
|
|
138
136
|
apply_autocommit!(sel)
|
139
137
|
apply_txn_opts!(sel)
|
140
138
|
suppress_read_write_concern!(sel)
|
141
|
-
|
139
|
+
validate_read_preference!(sel)
|
142
140
|
update_session_state!
|
143
141
|
apply_txn_num!(sel)
|
144
142
|
end
|
data/lib/mongo/protocol/query.rb
CHANGED
@@ -301,6 +301,7 @@ module Mongo
|
|
301
301
|
OPTION_MAPPINGS.each do |legacy, option|
|
302
302
|
document.store(option, options[legacy]) unless options[legacy].nil?
|
303
303
|
end
|
304
|
+
Mongo::Lint.validate_camel_case_read_preference(filter['readPreference'])
|
304
305
|
SPECIAL_FIELD_MAPPINGS.each do |special, normal|
|
305
306
|
document.store(normal, filter[special]) unless filter[special].nil?
|
306
307
|
end
|
data/lib/mongo/server.rb
CHANGED
@@ -47,7 +47,7 @@ module Mongo
|
|
47
47
|
# @example Check a connection out from the pool.
|
48
48
|
# pool.checkout
|
49
49
|
#
|
50
|
-
# @return [ Mongo::
|
50
|
+
# @return [ Mongo::Server::Connection ] The checked out connection.
|
51
51
|
#
|
52
52
|
# @since 2.0.0
|
53
53
|
def checkout
|
@@ -120,14 +120,14 @@ module Mongo
|
|
120
120
|
|
121
121
|
class << self
|
122
122
|
|
123
|
-
#
|
123
|
+
# Creates a new connection pool for the provided server.
|
124
124
|
#
|
125
|
-
# @example
|
126
|
-
# Mongo::
|
125
|
+
# @example Create a new connection pool.
|
126
|
+
# Mongo::Server::ConnectionPool.get(server)
|
127
127
|
#
|
128
128
|
# @param [ Mongo::Server ] server The server.
|
129
129
|
#
|
130
|
-
# @return [ Mongo::
|
130
|
+
# @return [ Mongo::Server::ConnectionPool ] The connection pool.
|
131
131
|
#
|
132
132
|
# @since 2.0.0
|
133
133
|
def get(server)
|
@@ -53,7 +53,7 @@ module Mongo
|
|
53
53
|
# @example Dequeue a connection.
|
54
54
|
# queue.dequeue
|
55
55
|
#
|
56
|
-
# @return [ Mongo::
|
56
|
+
# @return [ Mongo::Server::Connection ] The next connection.
|
57
57
|
#
|
58
58
|
# @since 2.0.0
|
59
59
|
def dequeue
|
@@ -82,7 +82,7 @@ module Mongo
|
|
82
82
|
# @example Enqueue a connection.
|
83
83
|
# queue.enqueue(connection)
|
84
84
|
#
|
85
|
-
# @param [ Mongo::
|
85
|
+
# @param [ Mongo::Server::Connection ] connection The connection.
|
86
86
|
#
|
87
87
|
# @since 2.0.0
|
88
88
|
def enqueue(connection)
|
@@ -96,7 +96,7 @@ module Mongo
|
|
96
96
|
# the initial size of the queue.
|
97
97
|
#
|
98
98
|
# @example Create the queue.
|
99
|
-
# Mongo::
|
99
|
+
# Mongo::Server::ConnectionPool::Queue.new(max_pool_size: 5) { Connection.new }
|
100
100
|
#
|
101
101
|
# @param [ Hash ] options The options.
|
102
102
|
#
|
@@ -124,7 +124,7 @@ module Mongo
|
|
124
124
|
#
|
125
125
|
# @since 2.0.0
|
126
126
|
def inspect
|
127
|
-
"#<Mongo::
|
127
|
+
"#<Mongo::Server::ConnectionPool::Queue:0x#{object_id} min_size=#{min_size} max_size=#{max_size} " +
|
128
128
|
"wait_timeout=#{wait_timeout} current_size=#{queue.size}>"
|
129
129
|
end
|
130
130
|
|
@@ -71,6 +71,7 @@ module Mongo
|
|
71
71
|
# @since 2.0.0
|
72
72
|
def get(preference = {})
|
73
73
|
return preference if PREFERENCES.values.include?(preference.class)
|
74
|
+
Mongo::Lint.validate_underscore_read_preference(preference)
|
74
75
|
PREFERENCES.fetch((preference[:mode] || :primary).to_sym).new(preference)
|
75
76
|
end
|
76
77
|
end
|
data/lib/mongo/session.rb
CHANGED
@@ -110,9 +110,16 @@ module Mongo
|
|
110
110
|
# @param [ Client ] client The client through which this session is created.
|
111
111
|
# @param [ Hash ] options The options for this session.
|
112
112
|
#
|
113
|
+
# @option options [ Hash ] :read_preference The read preference options hash,
|
114
|
+
# with the following optional keys:
|
115
|
+
# - *:mode* -- the read preference as a string or symbol; valid values are
|
116
|
+
# *:primary*, *:primary_preferred*, *:secondary*, *:secondary_preferred*
|
117
|
+
# and *:nearest*.
|
118
|
+
#
|
113
119
|
# @since 2.5.0
|
114
120
|
def initialize(server_session, client, options = {})
|
115
121
|
@server_session = server_session
|
122
|
+
options = options.dup
|
116
123
|
|
117
124
|
# Because the read preference will need to be inserted into a command as a string, we convert
|
118
125
|
# it from a symbol immediately upon receiving it.
|
@@ -121,7 +128,7 @@ module Mongo
|
|
121
128
|
end
|
122
129
|
|
123
130
|
@client = client.use(:admin)
|
124
|
-
@options = options.
|
131
|
+
@options = options.freeze
|
125
132
|
@cluster_time = nil
|
126
133
|
@state = NO_TRANSACTION_STATE
|
127
134
|
end
|
@@ -232,7 +239,13 @@ module Mongo
|
|
232
239
|
def add_txn_opts!(command, read)
|
233
240
|
command.tap do |c|
|
234
241
|
# The read preference should be added for all read operations.
|
235
|
-
|
242
|
+
if read && txn_read_pref = txn_read_preference
|
243
|
+
Mongo::Lint.validate_underscore_read_preference(txn_read_pref)
|
244
|
+
txn_read_pref = txn_read_pref.dup
|
245
|
+
txn_read_pref[:mode] = txn_read_pref[:mode].to_s.gsub(/(_\w)/) { |match| match[1].upcase }
|
246
|
+
Mongo::Lint.validate_camel_case_read_preference(txn_read_pref)
|
247
|
+
c['$readPreference'] = txn_read_pref
|
248
|
+
end
|
236
249
|
|
237
250
|
# The read concern should be added to any command that starts a transaction.
|
238
251
|
if starting_transaction? && txn_read_concern
|
@@ -277,14 +290,14 @@ module Mongo
|
|
277
290
|
# Ensure that the read preference of a command primary.
|
278
291
|
#
|
279
292
|
# @example
|
280
|
-
# session.
|
293
|
+
# session.validate_read_preference!(command)
|
281
294
|
#
|
282
295
|
# @raise [ Mongo::Error::InvalidTransactionOperation ] If the read preference of the command is
|
283
296
|
# not primary.
|
284
297
|
#
|
285
298
|
# @since 2.6.0
|
286
|
-
def
|
287
|
-
return unless in_transaction? &&
|
299
|
+
def validate_read_preference!(command)
|
300
|
+
return unless in_transaction? && non_primary_read_preference_mode?(command)
|
288
301
|
|
289
302
|
raise Mongo::Error::InvalidTransactionOperation.new(
|
290
303
|
Mongo::Error::InvalidTransactionOperation::INVALID_READ_PREFERENCE)
|
@@ -452,14 +465,29 @@ module Mongo
|
|
452
465
|
|
453
466
|
# Start a new transaction.
|
454
467
|
#
|
455
|
-
# Note that the transaction will not be started on the server until an
|
456
|
-
# after start_transaction is called.
|
468
|
+
# Note that the transaction will not be started on the server until an
|
469
|
+
# operation is performed after start_transaction is called.
|
457
470
|
#
|
458
471
|
# @example Start a new transaction
|
459
472
|
# session.start_transaction(options)
|
460
473
|
#
|
461
|
-
# @
|
462
|
-
#
|
474
|
+
# @param [ Hash ] options The options for the transaction being started.
|
475
|
+
#
|
476
|
+
# @option options [ Hash ] read_concern The read concern options hash, with the following
|
477
|
+
# optional keys:
|
478
|
+
# - *:level* -- the read preference level as a symbol; valid values are *:local*, *:majority*,
|
479
|
+
# and *:snapshot*
|
480
|
+
# - *:after_cluster_time* -- the cluster time BSON::Document or hash specifying which cluster
|
481
|
+
# time reads should occur after
|
482
|
+
# @option options [ Hash ] :write_concern The write concern options. Can be :w =>
|
483
|
+
# Integer|String, :fsync => Boolean, :j => Boolean.
|
484
|
+
# @option options [ Hash ] :read The read preference options. The hash may have the following
|
485
|
+
# items:
|
486
|
+
# - *:mode* -- read preference specified as a symbol; the only valid value is
|
487
|
+
# *:primary*.
|
488
|
+
#
|
489
|
+
# @raise [ InvalidTransactionOperation ] If a transaction is already in
|
490
|
+
# progress or if the write concern is unacknowledged.
|
463
491
|
#
|
464
492
|
# @since 2.6.0
|
465
493
|
def start_transaction(options = nil)
|
@@ -594,18 +622,21 @@ module Mongo
|
|
594
622
|
within_states?(STARTING_TRANSACTION_STATE, TRANSACTION_IN_PROGRESS_STATE)
|
595
623
|
end
|
596
624
|
|
597
|
-
# Get the read preference
|
625
|
+
# Get the read preference the session will use in the currently
|
626
|
+
# active transaction.
|
627
|
+
#
|
628
|
+
# This is a driver style hash with underscore keys.
|
598
629
|
#
|
599
630
|
# @example Get the transaction's read preference
|
600
|
-
# session.
|
631
|
+
# session.txn_read_preference
|
601
632
|
#
|
602
|
-
# @return [ Hash ] The read preference
|
633
|
+
# @return [ Hash ] The read preference of the transaction.
|
603
634
|
#
|
604
635
|
# @since 2.6.0
|
605
|
-
def
|
606
|
-
rp =
|
607
|
-
|
608
|
-
|
636
|
+
def txn_read_preference
|
637
|
+
rp = txn_options && txn_options[:read_preference] ||
|
638
|
+
@client.read_preference
|
639
|
+
Mongo::Lint.validate_underscore_read_preference(rp)
|
609
640
|
rp
|
610
641
|
end
|
611
642
|
|
@@ -639,7 +670,7 @@ module Mongo
|
|
639
670
|
(@client.write_concern && @client.write_concern.options)
|
640
671
|
end
|
641
672
|
|
642
|
-
def
|
673
|
+
def non_primary_read_preference_mode?(command)
|
643
674
|
return false unless command['$readPreference']
|
644
675
|
|
645
676
|
mode = command['$readPreference']['mode'] || command['$readPreference'][:mode]
|