mongo 2.12.0.rc0 → 2.12.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 +0 -0
- data/README.md +2 -1
- data/lib/mongo/client.rb +23 -9
- data/lib/mongo/client_encryption.rb +1 -1
- data/lib/mongo/cluster.rb +6 -2
- data/lib/mongo/crypt/auto_decryption_context.rb +3 -5
- data/lib/mongo/crypt/auto_encrypter.rb +17 -7
- data/lib/mongo/crypt/binding.rb +446 -379
- data/lib/mongo/crypt/context.rb +4 -4
- data/lib/mongo/crypt/encryption_io.rb +16 -10
- data/lib/mongo/crypt/explicit_encrypter.rb +3 -3
- data/lib/mongo/crypt/explicit_encryption_context.rb +1 -1
- data/lib/mongo/crypt/handle.rb +26 -4
- data/lib/mongo/crypt/hooks.rb +1 -1
- data/lib/mongo/database.rb +11 -1
- data/lib/mongo/error/bulk_write_error.rb +16 -14
- data/lib/mongo/error/notable.rb +0 -15
- data/lib/mongo/error/parser.rb +1 -1
- data/lib/mongo/grid/file/info.rb +1 -1
- data/lib/mongo/monitoring/event/cmap/connection_check_out_failed.rb +1 -1
- data/lib/mongo/operation/insert/command.rb +3 -2
- data/lib/mongo/operation/insert/legacy.rb +2 -1
- data/lib/mongo/operation/insert/op_msg.rb +1 -1
- data/lib/mongo/operation/shared/executable.rb +9 -9
- data/lib/mongo/operation/shared/op_msg_or_command.rb +2 -2
- data/lib/mongo/operation/shared/read_preference_supported.rb +68 -19
- data/lib/mongo/operation/shared/response_handling.rb +1 -1
- data/lib/mongo/operation/shared/sessions_supported.rb +44 -3
- data/lib/mongo/protocol/bit_vector.rb +2 -1
- data/lib/mongo/protocol/message.rb +22 -7
- data/lib/mongo/protocol/msg.rb +2 -5
- data/lib/mongo/protocol/serializers.rb +32 -11
- data/lib/mongo/retryable.rb +1 -1
- data/lib/mongo/server/connection.rb +1 -1
- data/lib/mongo/server/connection_base.rb +9 -4
- data/lib/mongo/server/connection_pool/populator.rb +1 -1
- data/lib/mongo/session.rb +1 -1
- data/lib/mongo/srv/monitor.rb +73 -42
- data/lib/mongo/srv/result.rb +0 -1
- data/lib/mongo/uri.rb +1 -1
- data/lib/mongo/uri/srv_protocol.rb +1 -1
- data/lib/mongo/version.rb +1 -1
- data/mongo.gemspec +0 -2
- data/spec/README.md +106 -12
- data/spec/integration/client_construction_spec.rb +29 -5
- data/spec/integration/client_side_encryption/auto_encryption_bulk_writes_spec.rb +6 -4
- data/spec/integration/client_side_encryption/auto_encryption_command_monitoring_spec.rb +19 -17
- data/spec/integration/client_side_encryption/auto_encryption_mongocryptd_spawn_spec.rb +5 -4
- data/spec/integration/client_side_encryption/auto_encryption_old_wire_version_spec.rb +11 -8
- data/spec/integration/client_side_encryption/auto_encryption_reconnect_spec.rb +14 -9
- data/spec/integration/client_side_encryption/auto_encryption_spec.rb +46 -45
- data/spec/integration/client_side_encryption/bson_size_limit_spec.rb +11 -7
- data/spec/integration/client_side_encryption/bypass_mongocryptd_spawn_spec.rb +13 -9
- data/spec/integration/client_side_encryption/client_close_spec.rb +10 -6
- data/spec/integration/client_side_encryption/corpus_spec.rb +19 -14
- data/spec/integration/client_side_encryption/data_key_spec.rb +10 -8
- data/spec/integration/client_side_encryption/external_key_vault_spec.rb +12 -8
- data/spec/integration/client_side_encryption/views_spec.rb +6 -4
- data/spec/integration/client_update_spec.rb +36 -2
- data/spec/integration/crud_spec.rb +89 -0
- data/spec/integration/read_preference_spec.rb +26 -0
- data/spec/integration/srv_monitoring_spec.rb +2 -2
- data/spec/kerberos/kerberos_spec.rb +87 -0
- data/spec/lite_spec_helper.rb +4 -8
- data/spec/mongo/bulk_write/result_spec.rb +11 -7
- data/spec/mongo/client_encryption_spec.rb +3 -6
- data/spec/mongo/crypt/auto_encrypter_spec.rb +8 -3
- data/spec/mongo/crypt/handle_spec.rb +38 -4
- data/spec/mongo/error/bulk_write_error_spec.rb +49 -0
- data/spec/mongo/error/notable_spec.rb +59 -0
- data/spec/mongo/operation/find/legacy_spec.rb +1 -0
- data/spec/mongo/operation/read_preference_legacy_spec.rb +351 -0
- data/spec/mongo/operation/read_preference_op_msg_spec.rb +194 -0
- data/spec/mongo/srv/monitor_spec.rb +88 -69
- data/spec/runners/transactions.rb +5 -7
- data/spec/spec_tests/client_side_encryption_spec.rb +0 -5
- data/spec/spec_tests/data/client_side_encryption/bulk.yml +3 -0
- data/spec/spec_tests/data/client_side_encryption/replaceOne.yml +4 -1
- data/spec/spec_tests/data/client_side_encryption/updateOne.yml +3 -0
- data/spec/support/cluster_tools.rb +6 -1
- data/spec/support/crypt.rb +14 -0
- data/spec/support/lite_constraints.rb +3 -1
- data/spec/support/spec_config.rb +10 -0
- data/spec/support/utils.rb +9 -1
- metadata +15 -14
- metadata.gz.sig +0 -0
- data/lib/mongo/cluster/srv_monitor.rb +0 -127
- data/lib/mongo/srv/warning_result.rb +0 -35
- data/spec/enterprise_auth/kerberos_spec.rb +0 -58
- data/spec/mongo/cluster/srv_monitor_spec.rb +0 -214
- data/spec/mongo/operation/read_preference_spec.rb +0 -245
data/lib/mongo/crypt/context.rb
CHANGED
@@ -26,11 +26,11 @@ module Mongo
|
|
26
26
|
class Context
|
27
27
|
# Create a new Context object
|
28
28
|
#
|
29
|
-
# @param [
|
30
|
-
# used to create a new
|
31
|
-
# @param [ ClientEncryption::IO ]
|
29
|
+
# @param [ Mongo::Crypt::Handle ] mongocrypt_handle A handle to libmongocrypt
|
30
|
+
# used to create a new context object.
|
31
|
+
# @param [ ClientEncryption::IO ] io An instance of the IO class
|
32
32
|
# that implements driver I/O methods required to run the
|
33
|
-
# state machine
|
33
|
+
# state machine.
|
34
34
|
def initialize(mongocrypt_handle, io)
|
35
35
|
# Ideally, this level of the API wouldn't be passing around pointer
|
36
36
|
# references between objects, so this method signature is subject to change.
|
@@ -29,15 +29,15 @@ module Mongo
|
|
29
29
|
# Creates a new EncryptionIO object with information about how to connect
|
30
30
|
# to the key vault.
|
31
31
|
#
|
32
|
-
# @param [ Mongo::Client ] client
|
32
|
+
# @param [ Mongo::Client ] client The client used to connect to the collection
|
33
33
|
# that stores the encrypted documents, defaults to nil.
|
34
|
-
# @param [ Mongo::Client ] mongocryptd_client
|
34
|
+
# @param [ Mongo::Client ] mongocryptd_client The client connected to mongocryptd,
|
35
35
|
# defaults to nil.
|
36
|
-
# @param [ Mongo::Client ] key_vault_client
|
36
|
+
# @param [ Mongo::Client ] key_vault_client The client connected to the
|
37
37
|
# key vault collection.
|
38
|
-
# @param [ String ] key_vault_namespace
|
38
|
+
# @param [ String ] key_vault_namespace The key vault namespace in the format
|
39
39
|
# db_name.collection_name.
|
40
|
-
# @param [ Hash ] mongocryptd_options
|
40
|
+
# @param [ Hash ] mongocryptd_options Options related to mongocryptd.
|
41
41
|
#
|
42
42
|
# @option mongocryptd_options [ Boolean ] :mongocryptd_bypass_spawn
|
43
43
|
# @option mongocryptd_options [ String ] :mongocryptd_spawn_path
|
@@ -105,13 +105,17 @@ module Mongo
|
|
105
105
|
raise ArgumentError, 'mark_command requires mongocryptd_client to have been passed to the constructor, but it was not'
|
106
106
|
end
|
107
107
|
|
108
|
+
# Ensure the response from mongocryptd is deserialized with { mode: :bson }
|
109
|
+
# to prevent losing type information in commands
|
110
|
+
options = { execution_options: { deserialize_as_bson: true } }
|
111
|
+
|
108
112
|
begin
|
109
|
-
response = @mongocryptd_client.database.command(cmd)
|
113
|
+
response = @mongocryptd_client.database.command(cmd, options)
|
110
114
|
rescue Error::NoServerAvailable => e
|
111
115
|
raise e if @options[:mongocryptd_bypass_spawn]
|
112
116
|
|
113
117
|
spawn_mongocryptd
|
114
|
-
response = @mongocryptd_client.database.command(cmd)
|
118
|
+
response = @mongocryptd_client.database.command(cmd, options)
|
115
119
|
end
|
116
120
|
|
117
121
|
return response.first
|
@@ -179,7 +183,8 @@ module Mongo
|
|
179
183
|
def key_vault_collection
|
180
184
|
@key_vault_collection ||= @key_vault_client.with(
|
181
185
|
database: @key_vault_db_name,
|
182
|
-
read_concern: { level: :majority }
|
186
|
+
read_concern: { level: :majority },
|
187
|
+
write_concern: { w: :majority }
|
183
188
|
)[@key_vault_collection_name]
|
184
189
|
end
|
185
190
|
|
@@ -233,8 +238,9 @@ module Mongo
|
|
233
238
|
|
234
239
|
# Provide an SSL socket to be used for KMS calls in a block API
|
235
240
|
#
|
236
|
-
# @param [ String ] endpoint The URI at which to connect the SSL socket
|
237
|
-
# @
|
241
|
+
# @param [ String ] endpoint The URI at which to connect the SSL socket.
|
242
|
+
# @yieldparam [ OpenSSL::SSL::SSLSocket ] ssl_socket Yields an SSL socket
|
243
|
+
# connected to the specified endpoint.
|
238
244
|
#
|
239
245
|
# @raise [ Mongo::Error::KmsError ] If the socket times out or raises
|
240
246
|
# an exception
|
@@ -22,9 +22,9 @@ module Mongo
|
|
22
22
|
class ExplicitEncrypter
|
23
23
|
# Create a new ExplicitEncrypter object.
|
24
24
|
#
|
25
|
-
# @
|
25
|
+
# @param [ Mongo::Client ] key_vault_client An instance of Mongo::Client
|
26
26
|
# to connect to the key vault collection.
|
27
|
-
# @
|
27
|
+
# @param [ String ] key_vault_namespace The namespace of the key vault
|
28
28
|
# collection in the format "db_name.collection_name".
|
29
29
|
# @option options [ Hash ] :kms_providers A hash of key management service
|
30
30
|
# configuration information. Valid hash keys are :local or :aws. There
|
@@ -44,7 +44,7 @@ module Mongo
|
|
44
44
|
#
|
45
45
|
# @param [ String ] kms_provider The KMS provider to use. Valid values are
|
46
46
|
# "aws" and "local".
|
47
|
-
# @
|
47
|
+
# @param [ Hash ] options
|
48
48
|
#
|
49
49
|
# @option options [ Hash ] :master_key Information about the AWS master key. Required
|
50
50
|
# if kms_provider is "aws".
|
@@ -38,7 +38,7 @@ module Mongo
|
|
38
38
|
# value. Valid algorithms are "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic"
|
39
39
|
# or "AEAD_AES_256_CBC_HMAC_SHA_512-Random"
|
40
40
|
#
|
41
|
-
# @
|
41
|
+
# @raise [ ArgumentError|Mongo::Error::CryptError ] If invalid options are provided
|
42
42
|
def initialize(mongocrypt, io, doc, options={})
|
43
43
|
super(mongocrypt, io)
|
44
44
|
|
data/lib/mongo/crypt/handle.rb
CHANGED
@@ -269,10 +269,8 @@ module Mongo
|
|
269
269
|
access_key_id = kms_providers[:aws][:access_key_id]
|
270
270
|
secret_access_key = kms_providers[:aws][:secret_access_key]
|
271
271
|
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
unless valid_access_key_id && valid_secret_access_key
|
272
|
+
unless kms_providers[:aws].key?(:access_key_id) &&
|
273
|
+
kms_providers[:aws].key?(:secret_access_key)
|
276
274
|
raise ArgumentError.new(
|
277
275
|
"The specified aws kms_providers option is invalid: #{kms_providers[:aws]}. " +
|
278
276
|
"kms_providers with :aws key must be in the format: " +
|
@@ -280,6 +278,30 @@ module Mongo
|
|
280
278
|
)
|
281
279
|
end
|
282
280
|
|
281
|
+
%i(access_key_id secret_access_key).each do |key|
|
282
|
+
value = kms_providers[:aws][key]
|
283
|
+
if value.nil?
|
284
|
+
raise ArgumentError.new(
|
285
|
+
"The aws #{key} option must be a String with at least one character; " \
|
286
|
+
"currently have nil"
|
287
|
+
)
|
288
|
+
end
|
289
|
+
|
290
|
+
unless value.is_a?(String)
|
291
|
+
raise ArgumentError.new(
|
292
|
+
"The aws #{key} option must be a String with at least one character; " \
|
293
|
+
"currently have #{value}"
|
294
|
+
)
|
295
|
+
end
|
296
|
+
|
297
|
+
if value.empty?
|
298
|
+
raise ArgumentError.new(
|
299
|
+
"The aws #{key} option must be a String with at least one character; " \
|
300
|
+
"it is currently an empty string"
|
301
|
+
)
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
283
305
|
Binding.setopt_kms_provider_aws(self, access_key_id, secret_access_key)
|
284
306
|
end
|
285
307
|
|
data/lib/mongo/crypt/hooks.rb
CHANGED
@@ -62,7 +62,7 @@ module Mongo
|
|
62
62
|
|
63
63
|
# An HMAC SHA-512 or SHA-256 function
|
64
64
|
#
|
65
|
-
# @param [ String ] The name of the digest, either "SHA256" or "SHA512"
|
65
|
+
# @param [ String ] digest_name The name of the digest, either "SHA256" or "SHA512"
|
66
66
|
# @param [ String ] key The 32-byte AES encryption key
|
67
67
|
# @param [ String ] input The data to be tagged
|
68
68
|
#
|
data/lib/mongo/database.rb
CHANGED
@@ -162,9 +162,18 @@ module Mongo
|
|
162
162
|
#
|
163
163
|
# @option opts :read [ Hash ] The read preference for this command.
|
164
164
|
# @option opts :session [ Session ] The session to use for this command.
|
165
|
+
# @option opts :execution_options [ Hash ] Options to pass to the code that
|
166
|
+
# executes this command. This is an internal option and is subject to
|
167
|
+
# change.
|
168
|
+
# - :deserialize_as_bson [ Boolean ] Whether to deserialize the response
|
169
|
+
# to this command using BSON types intead of native Ruby types wherever
|
170
|
+
# possible.
|
165
171
|
#
|
166
172
|
# @return [ Mongo::Operation::Result ] The result of the command execution.
|
167
173
|
def command(operation, opts = {})
|
174
|
+
opts = opts.dup
|
175
|
+
execution_opts = opts.delete(:execution_options) || {}
|
176
|
+
|
168
177
|
txn_read_pref = if opts[:session] && opts[:session].in_transaction?
|
169
178
|
opts[:session].txn_read_preference
|
170
179
|
else
|
@@ -182,7 +191,8 @@ module Mongo
|
|
182
191
|
:read => selector,
|
183
192
|
:session => session
|
184
193
|
)
|
185
|
-
|
194
|
+
|
195
|
+
op.execute(server, client: client, options: execution_opts)
|
186
196
|
end
|
187
197
|
end
|
188
198
|
|
@@ -35,22 +35,24 @@ module Mongo
|
|
35
35
|
# @since 2.0.0
|
36
36
|
def initialize(result)
|
37
37
|
@result = result
|
38
|
+
# Exception constructor behaves differently for a nil argument and
|
39
|
+
# for no argument. Avoid passing nil explicitly.
|
40
|
+
super(*[build_message])
|
38
41
|
end
|
39
42
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
"#{self.class}: #{messages}" + notes_tail
|
43
|
+
private
|
44
|
+
|
45
|
+
def build_message
|
46
|
+
errors = @result['writeErrors']
|
47
|
+
return nil unless errors
|
48
|
+
|
49
|
+
fragment = errors.first(10).map do |error|
|
50
|
+
"#{error['errmsg']} (#{error['code']})"
|
51
|
+
end.join(', ')
|
52
|
+
|
53
|
+
fragment += '...' if errors.length > 10
|
54
|
+
|
55
|
+
fragment
|
54
56
|
end
|
55
57
|
end
|
56
58
|
end
|
data/lib/mongo/error/notable.rb
CHANGED
@@ -45,26 +45,11 @@ module Mongo
|
|
45
45
|
@notes << note
|
46
46
|
end
|
47
47
|
|
48
|
-
# @api public
|
49
|
-
def message
|
50
|
-
super + notes_tail
|
51
|
-
end
|
52
|
-
|
53
48
|
# @api public
|
54
49
|
def to_s
|
55
50
|
super + notes_tail
|
56
51
|
end
|
57
52
|
|
58
|
-
# @api public
|
59
|
-
def inspect
|
60
|
-
msg = super
|
61
|
-
if msg.end_with?('>')
|
62
|
-
msg[0...msg.length-1] + notes_tail + '>'
|
63
|
-
else
|
64
|
-
msg + notes_tail
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
53
|
private
|
69
54
|
|
70
55
|
# @api private
|
data/lib/mongo/error/parser.rb
CHANGED
@@ -76,7 +76,7 @@ module Mongo
|
|
76
76
|
# examined because the status (ok: 1) is not part of the document and
|
77
77
|
# there is no way to distinguish successful from failed responses using
|
78
78
|
# the document itself, and a successful response may legitimately have
|
79
|
-
# {code: 123, codeName: 'foo'} as the contents of a user-inserted
|
79
|
+
# { code: 123, codeName: 'foo' } as the contents of a user-inserted
|
80
80
|
# document. The legacy server versions do not fill out code nor codeName
|
81
81
|
# thus not reading them does not lose information.
|
82
82
|
#
|
data/lib/mongo/grid/file/info.rb
CHANGED
@@ -204,7 +204,7 @@ module Mongo
|
|
204
204
|
# @note This method is transitional and is provided for backwards compatibility.
|
205
205
|
# It will be removed when md5 support is deprecated entirely.
|
206
206
|
#
|
207
|
-
# @param [ String ] The bytes to use to update the digest.
|
207
|
+
# @param [ String ] bytes The bytes to use to update the digest.
|
208
208
|
#
|
209
209
|
# @return [ Digest::MD5 ] The md5 hash object.
|
210
210
|
#
|
@@ -32,8 +32,9 @@ module Mongo
|
|
32
32
|
|
33
33
|
private
|
34
34
|
|
35
|
-
def get_result(server, client)
|
36
|
-
|
35
|
+
def get_result(server, client, options = {})
|
36
|
+
# This is a Mongo::Operation::Insert::Result
|
37
|
+
Result.new(*dispatch_message(server, client), @ids)
|
37
38
|
end
|
38
39
|
|
39
40
|
def selector(server)
|
@@ -22,11 +22,11 @@ module Mongo
|
|
22
22
|
|
23
23
|
include ResponseHandling
|
24
24
|
|
25
|
-
def do_execute(server, client)
|
25
|
+
def do_execute(server, client, options = {})
|
26
26
|
unpin_maybe(session) do
|
27
27
|
add_error_labels do
|
28
28
|
add_server_diagnostics(server) do
|
29
|
-
get_result(server, client).tap do |result|
|
29
|
+
get_result(server, client, options).tap do |result|
|
30
30
|
process_result(result, server)
|
31
31
|
end
|
32
32
|
end
|
@@ -34,8 +34,8 @@ module Mongo
|
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
|
-
def execute(server, client:)
|
38
|
-
do_execute(server, client).tap do |result|
|
37
|
+
def execute(server, client:, options: {})
|
38
|
+
do_execute(server, client, options).tap do |result|
|
39
39
|
validate_result(result, server)
|
40
40
|
end
|
41
41
|
end
|
@@ -46,16 +46,16 @@ module Mongo
|
|
46
46
|
Result
|
47
47
|
end
|
48
48
|
|
49
|
-
def get_result(server, client)
|
50
|
-
result_class.new(dispatch_message(server, client))
|
49
|
+
def get_result(server, client, options = {})
|
50
|
+
result_class.new(dispatch_message(server, client, options))
|
51
51
|
end
|
52
52
|
|
53
|
-
# Returns a Protocol::Message or nil
|
54
|
-
def dispatch_message(server, client)
|
53
|
+
# Returns a Protocol::Message or nil as reply.
|
54
|
+
def dispatch_message(server, client, options = {})
|
55
55
|
server.with_connection do |connection|
|
56
56
|
message = build_message(server)
|
57
57
|
message = message.maybe_encrypt(server, client)
|
58
|
-
connection.dispatch([ message ], operation_id, client)
|
58
|
+
connection.dispatch([ message ], operation_id, client, options)
|
59
59
|
end
|
60
60
|
end
|
61
61
|
|
@@ -22,9 +22,9 @@ module Mongo
|
|
22
22
|
module OpMsgOrCommand
|
23
23
|
include PolymorphicLookup
|
24
24
|
|
25
|
-
def execute(server, client:)
|
25
|
+
def execute(server, client:, options: {})
|
26
26
|
operation = final_operation(server)
|
27
|
-
operation.execute(server, client: client)
|
27
|
+
operation.execute(server, client: client, options: options)
|
28
28
|
end
|
29
29
|
|
30
30
|
private
|
@@ -15,19 +15,83 @@
|
|
15
15
|
module Mongo
|
16
16
|
module Operation
|
17
17
|
|
18
|
-
#
|
18
|
+
# Read preference handling for pre-OP_MSG operation implementations.
|
19
|
+
#
|
20
|
+
# This module is not used by OP_MSG operation classes (those deriving
|
21
|
+
# from OpMsgBase). Instead, read preference for those classes is handled
|
22
|
+
# in SessionsSupported module.
|
19
23
|
#
|
20
24
|
# @since 2.5.2
|
25
|
+
# @api private
|
21
26
|
module ReadPreferenceSupported
|
22
27
|
|
23
28
|
private
|
24
29
|
|
25
|
-
|
26
|
-
|
30
|
+
# Get the options for executing the operation on a particular server.
|
31
|
+
#
|
32
|
+
# @param [ Server ] server The server that the operation will be
|
33
|
+
# executed on.
|
34
|
+
#
|
35
|
+
# @return [ Hash ] The options.
|
36
|
+
#
|
37
|
+
# @since 2.0.0
|
27
38
|
def options(server)
|
28
|
-
|
39
|
+
add_slave_ok_flag_maybe(super, server)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Adds :slave_ok flag to options based on the read preference specified
|
43
|
+
# in the operation or implied by the topology that the server is a
|
44
|
+
# part of.
|
45
|
+
#
|
46
|
+
# @param [ Hash ] options The options calculated so far.
|
47
|
+
#
|
48
|
+
# @return [ Hash ] The new options.
|
49
|
+
def add_slave_ok_flag_maybe(options, server)
|
50
|
+
add_flag =
|
51
|
+
# https://github.com/mongodb/specifications/blob/master/source/server-selection/server-selection.rst#topology-type-single
|
52
|
+
if server.standalone?
|
53
|
+
# Read preference is never sent to standalones.
|
54
|
+
false
|
55
|
+
elsif server.cluster.single?
|
56
|
+
# In Single topology the driver forces primaryPreferred read
|
57
|
+
# preference mode (via the slave_ok flag, in case of old servers)
|
58
|
+
# so that the query is satisfied.
|
59
|
+
true
|
60
|
+
else
|
61
|
+
# In replica sets and sharded clusters, read preference is passed
|
62
|
+
# to the server if one is specified by the application, and there
|
63
|
+
# is no default.
|
64
|
+
read && read.slave_ok?
|
65
|
+
end
|
66
|
+
|
67
|
+
if add_flag
|
68
|
+
options= options.dup
|
69
|
+
(options[:flags] ||= []) << :slave_ok
|
70
|
+
end
|
71
|
+
|
72
|
+
options
|
29
73
|
end
|
30
74
|
|
75
|
+
def command(server)
|
76
|
+
sel = super
|
77
|
+
update_selector_for_read_pref(sel, server)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Adds $readPreference field to the command document.
|
81
|
+
#
|
82
|
+
# $readPreference is only sent when the server is a mongos,
|
83
|
+
# following the rules described in
|
84
|
+
# https://github.com/mongodb/specifications/blob/master/source/server-selection/server-selection.rst#passing-read-preference-to-mongos.
|
85
|
+
# The topology does not matter for figuring out whether to send
|
86
|
+
# $readPreference since the decision is always made based on
|
87
|
+
# server type.
|
88
|
+
#
|
89
|
+
# $readPreference is not sent to pre-OP_MSG replica set members.
|
90
|
+
#
|
91
|
+
# @param [ Hash ] sel Existing command document.
|
92
|
+
# @param [ Server ] server The server that the command is to be sent to.
|
93
|
+
#
|
94
|
+
# @return [ Hash ] New command document to send to the server.
|
31
95
|
def update_selector_for_read_pref(sel, server)
|
32
96
|
if read && server.mongos? && read_pref = read.to_mongos
|
33
97
|
Mongo::Lint.validate_camel_case_read_preference(read_pref)
|
@@ -37,21 +101,6 @@ module Mongo
|
|
37
101
|
sel
|
38
102
|
end
|
39
103
|
end
|
40
|
-
|
41
|
-
def update_options_for_slave_ok(opts, server)
|
42
|
-
if (server.cluster.single? && !server.mongos?) || (read && read.slave_ok?)
|
43
|
-
opts.dup.tap do |o|
|
44
|
-
(o[:flags] ||= []) << SLAVE_OK
|
45
|
-
end
|
46
|
-
else
|
47
|
-
opts
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
def command(server)
|
52
|
-
sel = super
|
53
|
-
update_selector_for_read_pref(sel, server)
|
54
|
-
end
|
55
104
|
end
|
56
105
|
end
|
57
106
|
end
|