mongo 2.6.0 → 2.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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]
|