mongo 2.24.1 → 2.25.0
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
- data/bin/mongo_console +2 -2
- data/lib/mongo/address/validator.rb +1 -1
- data/lib/mongo/address.rb +1 -3
- data/lib/mongo/auth/aws/conversation.rb +0 -4
- data/lib/mongo/auth/aws/credentials_retriever.rb +3 -8
- data/lib/mongo/auth/base.rb +1 -1
- data/lib/mongo/auth/sasl_conversation_base.rb +1 -1
- data/lib/mongo/auth/scram_conversation_base.rb +1 -8
- data/lib/mongo/auth/stringprep.rb +1 -6
- data/lib/mongo/auth/user/view.rb +1 -1
- data/lib/mongo/bulk_write/result_combiner.rb +3 -3
- data/lib/mongo/bulk_write.rb +1 -1
- data/lib/mongo/client.rb +82 -12
- data/lib/mongo/cluster/reapers/cursor_reaper.rb +12 -5
- data/lib/mongo/cluster/sdam_flow.rb +4 -4
- data/lib/mongo/cluster/topology/base.rb +1 -1
- data/lib/mongo/cluster.rb +12 -28
- data/lib/mongo/collection/view/aggregation/behavior.rb +1 -1
- data/lib/mongo/collection/view/aggregation.rb +2 -4
- data/lib/mongo/collection/view/builder/aggregation.rb +3 -5
- data/lib/mongo/collection/view/builder/map_reduce.rb +1 -1
- data/lib/mongo/collection/view/change_stream.rb +14 -9
- data/lib/mongo/collection/view/map_reduce.rb +2 -11
- data/lib/mongo/collection/view/readable.rb +11 -7
- data/lib/mongo/collection/view/writable.rb +4 -4
- data/lib/mongo/collection/view.rb +8 -4
- data/lib/mongo/collection.rb +1 -1
- data/lib/mongo/crypt/auto_encrypter.rb +1 -1
- data/lib/mongo/crypt/binary.rb +7 -4
- data/lib/mongo/crypt/binding.rb +88 -10
- data/lib/mongo/crypt/context.rb +50 -19
- data/lib/mongo/crypt/encryption_io.rb +11 -5
- data/lib/mongo/crypt/handle.rb +17 -5
- data/lib/mongo/crypt/kms/credentials.rb +70 -31
- data/lib/mongo/crypt/kms/kmip/master_document.rb +30 -1
- data/lib/mongo/crypt/kms/master_key_document.rb +11 -6
- data/lib/mongo/crypt/kms.rb +12 -1
- data/lib/mongo/cursor.rb +8 -2
- data/lib/mongo/database/cursor_command_view.rb +95 -0
- data/lib/mongo/database.rb +144 -18
- data/lib/mongo/error/invalid_uri.rb +5 -1
- data/lib/mongo/error/operation_failure.rb +2 -2
- data/lib/mongo/error/parser.rb +3 -3
- data/lib/mongo/error/sdam_error_detection.rb +2 -3
- data/lib/mongo/grid/fs_bucket.rb +27 -21
- data/lib/mongo/grid/stream/write.rb +2 -2
- data/lib/mongo/index/view.rb +13 -7
- data/lib/mongo/monitoring/event/cmap/connection_check_out_failed.rb +1 -0
- data/lib/mongo/monitoring/event/cmap/connection_check_out_started.rb +1 -0
- data/lib/mongo/monitoring/event/cmap/connection_checked_in.rb +1 -0
- data/lib/mongo/monitoring/event/cmap/connection_checked_out.rb +1 -0
- data/lib/mongo/monitoring/event/cmap/connection_closed.rb +1 -0
- data/lib/mongo/monitoring/event/cmap/connection_created.rb +1 -0
- data/lib/mongo/monitoring/event/cmap/connection_ready.rb +1 -0
- data/lib/mongo/monitoring/event/cmap/pool_cleared.rb +1 -0
- data/lib/mongo/monitoring/event/cmap/pool_closed.rb +1 -0
- data/lib/mongo/monitoring/event/cmap/pool_created.rb +1 -0
- data/lib/mongo/monitoring/event/cmap/pool_ready.rb +1 -0
- data/lib/mongo/monitoring/event/command_failed.rb +1 -0
- data/lib/mongo/monitoring/event/command_started.rb +1 -0
- data/lib/mongo/monitoring/event/command_succeeded.rb +1 -0
- data/lib/mongo/monitoring/event/secure.rb +12 -17
- data/lib/mongo/monitoring/event/server_closed.rb +1 -0
- data/lib/mongo/monitoring/event/server_description_changed.rb +1 -0
- data/lib/mongo/monitoring/event/server_heartbeat_failed.rb +1 -0
- data/lib/mongo/monitoring/event/server_heartbeat_started.rb +1 -0
- data/lib/mongo/monitoring/event/server_heartbeat_succeeded.rb +1 -0
- data/lib/mongo/monitoring/event/server_opening.rb +1 -0
- data/lib/mongo/monitoring/event/topology_changed.rb +1 -0
- data/lib/mongo/monitoring/event/topology_closed.rb +1 -0
- data/lib/mongo/monitoring/event/topology_opening.rb +1 -0
- data/lib/mongo/operation/create/op_msg.rb +1 -0
- data/lib/mongo/operation/create_index/op_msg.rb +2 -1
- data/lib/mongo/operation/cursor_command/op_msg.rb +37 -0
- data/lib/mongo/operation/cursor_command/result.rb +60 -0
- data/lib/mongo/operation/cursor_command.rb +33 -0
- data/lib/mongo/operation/delete/op_msg.rb +1 -0
- data/lib/mongo/operation/drop/op_msg.rb +1 -0
- data/lib/mongo/operation/drop_database/op_msg.rb +1 -0
- data/lib/mongo/operation/drop_index/op_msg.rb +1 -0
- data/lib/mongo/operation/find/builder/command.rb +1 -1
- data/lib/mongo/operation/insert/bulk_result.rb +2 -4
- data/lib/mongo/operation/insert/op_msg.rb +1 -0
- data/lib/mongo/operation/result.rb +12 -25
- data/lib/mongo/operation/shared/causal_consistency_supported.rb +4 -2
- data/lib/mongo/operation/shared/executable.rb +1 -9
- data/lib/mongo/operation/shared/result/aggregatable.rb +2 -2
- data/lib/mongo/operation/shared/sessions_supported.rb +3 -5
- data/lib/mongo/operation/update/bulk_result.rb +1 -1
- data/lib/mongo/operation/update/op_msg.rb +1 -0
- data/lib/mongo/operation/write_command/op_msg.rb +2 -0
- data/lib/mongo/operation.rb +1 -0
- data/lib/mongo/options/redacted.rb +2 -2
- data/lib/mongo/protocol/compressed.rb +15 -11
- data/lib/mongo/protocol/message.rb +16 -16
- data/lib/mongo/protocol/registry.rb +1 -1
- data/lib/mongo/protocol/serializers.rb +1 -3
- data/lib/mongo/query_cache.rb +3 -5
- data/lib/mongo/server/connection.rb +3 -1
- data/lib/mongo/server/connection_common.rb +9 -1
- data/lib/mongo/server/connection_pool/generation_manager.rb +1 -1
- data/lib/mongo/server/connection_pool.rb +24 -10
- data/lib/mongo/server/description/features.rb +1 -1
- data/lib/mongo/server/description.rb +1 -1
- data/lib/mongo/server/monitor/connection.rb +3 -2
- data/lib/mongo/server/monitor.rb +133 -30
- data/lib/mongo/server/pending_connection.rb +1 -0
- data/lib/mongo/server/push_monitor.rb +16 -2
- data/lib/mongo/server.rb +27 -7
- data/lib/mongo/server_selector/base.rb +3 -6
- data/lib/mongo/server_selector/secondary_preferred.rb +4 -1
- data/lib/mongo/session.rb +22 -23
- data/lib/mongo/socket/ssl.rb +3 -3
- data/lib/mongo/socket.rb +1 -7
- data/lib/mongo/srv/monitor.rb +11 -2
- data/lib/mongo/srv/resolver.rb +1 -1
- data/lib/mongo/srv/result.rb +5 -3
- data/lib/mongo/timeout.rb +10 -15
- data/lib/mongo/tracing/open_telemetry/command_tracer.rb +16 -2
- data/lib/mongo/uri/options_mapper.rb +21 -9
- data/lib/mongo/uri/srv_protocol.rb +4 -4
- data/lib/mongo/uri.rb +56 -8
- data/lib/mongo/utils.rb +1 -1
- data/lib/mongo/version.rb +1 -1
- metadata +6 -4
- data/lib/mongo/auth/stringprep/unicode_normalize/normalize.rb +0 -173
- data/lib/mongo/auth/stringprep/unicode_normalize/tables.rb +0 -1164
|
@@ -239,7 +239,7 @@ module Mongo
|
|
|
239
239
|
|
|
240
240
|
session.unpin unless session.in_transaction?
|
|
241
241
|
|
|
242
|
-
if server = session.pinned_server
|
|
242
|
+
if (server = session.pinned_server)
|
|
243
243
|
# Here we assume that a mongos stays in the topology indefinitely.
|
|
244
244
|
# This will no longer be the case once SRV polling is implemented.
|
|
245
245
|
|
|
@@ -398,9 +398,7 @@ module Mongo
|
|
|
398
398
|
# @api private
|
|
399
399
|
def candidates(cluster, deprioritized = [])
|
|
400
400
|
servers = cluster.servers.reject { |s| deprioritized.include?(s) }
|
|
401
|
-
if cluster.single?
|
|
402
|
-
servers
|
|
403
|
-
elsif cluster.sharded?
|
|
401
|
+
if cluster.single? || cluster.sharded?
|
|
404
402
|
servers
|
|
405
403
|
elsif cluster.replica_set?
|
|
406
404
|
select_in_replica_set(servers)
|
|
@@ -689,8 +687,7 @@ module Mongo
|
|
|
689
687
|
msg = ''
|
|
690
688
|
dead_monitors = []
|
|
691
689
|
cluster.servers_list.each do |server|
|
|
692
|
-
|
|
693
|
-
dead_monitors << server if thread.nil? || !thread.alive?
|
|
690
|
+
dead_monitors << server unless server.monitor&.running?
|
|
694
691
|
end
|
|
695
692
|
if dead_monitors.any?
|
|
696
693
|
msg += ". The following servers have dead monitor threads: #{dead_monitors.map(&:summary).join(', ')}"
|
|
@@ -101,7 +101,10 @@ module Mongo
|
|
|
101
101
|
#
|
|
102
102
|
# @since 2.0.0
|
|
103
103
|
def select_in_replica_set(candidates)
|
|
104
|
-
|
|
104
|
+
eligible = secondaries(candidates)
|
|
105
|
+
return near_servers(eligible) unless eligible.empty?
|
|
106
|
+
|
|
107
|
+
primary(candidates)
|
|
105
108
|
end
|
|
106
109
|
|
|
107
110
|
def max_staleness_allowed?
|
data/lib/mongo/session.rb
CHANGED
|
@@ -459,13 +459,9 @@ module Mongo
|
|
|
459
459
|
@inside_with_transaction = true
|
|
460
460
|
@with_transaction_timeout_ms = options&.dig(:timeout_ms) || @options[:default_timeout_ms] || @client.timeout_ms
|
|
461
461
|
@with_transaction_deadline = calculate_with_transaction_deadline(options)
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
else
|
|
466
|
-
# CSOT not enabled, so we use the default deadline, 120 seconds.
|
|
467
|
-
Utils.monotonic_time + 120
|
|
468
|
-
end
|
|
462
|
+
# When CSOT is enabled we have a customer defined deadline; otherwise
|
|
463
|
+
# fall back to the default deadline, 120 seconds.
|
|
464
|
+
deadline = @with_transaction_deadline || (Utils.monotonic_time + 120)
|
|
469
465
|
transaction_in_progress = false
|
|
470
466
|
transaction_attempt = 0
|
|
471
467
|
last_error = nil
|
|
@@ -1054,7 +1050,7 @@ module Mongo
|
|
|
1054
1050
|
# even if transaction's read concern is not set.
|
|
1055
1051
|
# Read concern here is the one sent to the server and may
|
|
1056
1052
|
# include afterClusterTime.
|
|
1057
|
-
if rc = c[:readConcern]
|
|
1053
|
+
if (rc = c[:readConcern])
|
|
1058
1054
|
rc = rc.dup
|
|
1059
1055
|
rc.delete(:level)
|
|
1060
1056
|
end
|
|
@@ -1201,7 +1197,7 @@ module Mongo
|
|
|
1201
1197
|
def process(result)
|
|
1202
1198
|
unless implicit?
|
|
1203
1199
|
set_operation_time(result)
|
|
1204
|
-
if cluster_time_doc = result.cluster_time
|
|
1200
|
+
if (cluster_time_doc = result.cluster_time)
|
|
1205
1201
|
advance_cluster_time(cluster_time_doc)
|
|
1206
1202
|
end
|
|
1207
1203
|
end
|
|
@@ -1312,8 +1308,6 @@ module Mongo
|
|
|
1312
1308
|
@inside_with_transaction
|
|
1313
1309
|
end
|
|
1314
1310
|
|
|
1315
|
-
private
|
|
1316
|
-
|
|
1317
1311
|
# Get the read concern the session will use when starting a transaction.
|
|
1318
1312
|
#
|
|
1319
1313
|
# This is a driver style hash with underscore keys.
|
|
@@ -1324,11 +1318,24 @@ module Mongo
|
|
|
1324
1318
|
# @return [ Hash ] The read concern used for starting transactions.
|
|
1325
1319
|
#
|
|
1326
1320
|
# @since 2.9.0
|
|
1321
|
+
# @api private
|
|
1327
1322
|
def txn_read_concern
|
|
1328
1323
|
# Read concern is inherited from client but not db or collection.
|
|
1329
1324
|
txn_options[:read_concern] || @client.read_concern
|
|
1330
1325
|
end
|
|
1331
1326
|
|
|
1327
|
+
# Returns causal consistency document if the last operation time is
|
|
1328
|
+
# known and causal consistency is enabled, otherwise returns nil.
|
|
1329
|
+
#
|
|
1330
|
+
# @api private
|
|
1331
|
+
def causal_consistency_doc
|
|
1332
|
+
return unless operation_time && causal_consistency?
|
|
1333
|
+
|
|
1334
|
+
{ afterClusterTime: operation_time }
|
|
1335
|
+
end
|
|
1336
|
+
|
|
1337
|
+
private
|
|
1338
|
+
|
|
1332
1339
|
def within_states?(*states)
|
|
1333
1340
|
states.include?(@state)
|
|
1334
1341
|
end
|
|
@@ -1346,14 +1353,6 @@ module Mongo
|
|
|
1346
1353
|
(@client.write_concern && @client.write_concern.options)
|
|
1347
1354
|
end
|
|
1348
1355
|
|
|
1349
|
-
# Returns causal consistency document if the last operation time is
|
|
1350
|
-
# known and causal consistency is enabled, otherwise returns nil.
|
|
1351
|
-
def causal_consistency_doc
|
|
1352
|
-
return unless operation_time && causal_consistency?
|
|
1353
|
-
|
|
1354
|
-
{ afterClusterTime: operation_time }
|
|
1355
|
-
end
|
|
1356
|
-
|
|
1357
1356
|
def causal_consistency?
|
|
1358
1357
|
@causal_consistency ||= if @options.key?(:causal_consistency)
|
|
1359
1358
|
!!@options[:causal_consistency]
|
|
@@ -1391,9 +1390,9 @@ module Mongo
|
|
|
1391
1390
|
raise Mongo::Error::InvalidTransactionOperation,
|
|
1392
1391
|
'timeoutMS cannot be overridden inside a withTransaction callback'
|
|
1393
1392
|
end
|
|
1394
|
-
elsif timeout_ms = opts[:timeout_ms]
|
|
1393
|
+
elsif (timeout_ms = opts[:timeout_ms])
|
|
1395
1394
|
result[:operation_timeout_ms] = timeout_ms
|
|
1396
|
-
elsif default_timeout_ms = options[:default_timeout_ms]
|
|
1395
|
+
elsif (default_timeout_ms = options[:default_timeout_ms])
|
|
1397
1396
|
result[:operation_timeout_ms] = default_timeout_ms
|
|
1398
1397
|
end
|
|
1399
1398
|
end
|
|
@@ -1407,9 +1406,9 @@ module Mongo
|
|
|
1407
1406
|
Utils.monotonic_time + (timeout / 1000.0)
|
|
1408
1407
|
end
|
|
1409
1408
|
}
|
|
1410
|
-
if timeout_ms = opts&.dig(:timeout_ms)
|
|
1409
|
+
if (timeout_ms = opts&.dig(:timeout_ms))
|
|
1411
1410
|
calc.call(timeout_ms)
|
|
1412
|
-
elsif default_timeout_ms = @options[:default_timeout_ms]
|
|
1411
|
+
elsif (default_timeout_ms = @options[:default_timeout_ms])
|
|
1413
1412
|
calc.call(default_timeout_ms)
|
|
1414
1413
|
elsif @client.timeout_ms
|
|
1415
1414
|
calc.call(@client.timeout_ms)
|
data/lib/mongo/socket/ssl.rb
CHANGED
|
@@ -359,7 +359,7 @@ module Mongo
|
|
|
359
359
|
if options[:ssl_cert]
|
|
360
360
|
cert_text = File.read(options[:ssl_cert])
|
|
361
361
|
cert_object = nil
|
|
362
|
-
elsif cert_text = options[:ssl_cert_string]
|
|
362
|
+
elsif (cert_text = options[:ssl_cert_string])
|
|
363
363
|
cert_object = nil
|
|
364
364
|
else
|
|
365
365
|
cert_object = options[:ssl_cert_object]
|
|
@@ -421,13 +421,13 @@ module Mongo
|
|
|
421
421
|
# https://github.com/jruby/jruby-openssl/issues/176
|
|
422
422
|
if BSON::Environment.jruby?
|
|
423
423
|
[ OpenSSL::PKey::RSA, OpenSSL::PKey::DSA ].each do |cls|
|
|
424
|
-
return cls.
|
|
424
|
+
return cls.new(*args)
|
|
425
425
|
rescue OpenSSL::PKey::PKeyError
|
|
426
426
|
# ignore
|
|
427
427
|
end
|
|
428
428
|
# Neither RSA nor DSA worked, fall through to trying PKey
|
|
429
429
|
end
|
|
430
|
-
OpenSSL::PKey.
|
|
430
|
+
OpenSSL::PKey.read(*args)
|
|
431
431
|
end
|
|
432
432
|
|
|
433
433
|
def set_cert_verification(context, options)
|
data/lib/mongo/socket.rb
CHANGED
|
@@ -547,10 +547,6 @@ module Mongo
|
|
|
547
547
|
!rv.nil?
|
|
548
548
|
end
|
|
549
549
|
|
|
550
|
-
def unix_socket?(sock)
|
|
551
|
-
defined?(UNIXSocket) && sock.is_a?(UNIXSocket)
|
|
552
|
-
end
|
|
553
|
-
|
|
554
550
|
DEFAULT_TCP_KEEPINTVL = 10
|
|
555
551
|
|
|
556
552
|
DEFAULT_TCP_KEEPCNT = 9
|
|
@@ -590,9 +586,7 @@ module Mongo
|
|
|
590
586
|
yield
|
|
591
587
|
rescue Errno::ETIMEDOUT => e
|
|
592
588
|
raise Error::SocketTimeoutError, "#{e.class}: #{e} (for #{human_address})"
|
|
593
|
-
rescue IOError, SystemCallError, ::SocketError => e
|
|
594
|
-
raise Error::SocketError, "#{e.class}: #{e} (for #{human_address})"
|
|
595
|
-
rescue OpenSSL::SSL::SSLError => e
|
|
589
|
+
rescue IOError, SystemCallError, ::SocketError, OpenSSL::SSL::SSLError => e
|
|
596
590
|
raise Error::SocketError, "#{e.class}: #{e} (for #{human_address})"
|
|
597
591
|
end
|
|
598
592
|
|
data/lib/mongo/srv/monitor.rb
CHANGED
|
@@ -42,10 +42,13 @@ module Mongo
|
|
|
42
42
|
# Options to pass through to Resolv::DNS constructor for SRV lookups.
|
|
43
43
|
def initialize(cluster, **opts)
|
|
44
44
|
@cluster = cluster
|
|
45
|
-
raise ArgumentError, 'SRV URI is required' unless @srv_uri = opts.delete(:srv_uri)
|
|
45
|
+
raise ArgumentError, 'SRV URI is required' unless (@srv_uri = opts.delete(:srv_uri))
|
|
46
46
|
|
|
47
47
|
@options = opts.freeze
|
|
48
|
-
|
|
48
|
+
# Per the polling-srv-records spec, mismatched-domain records and empty
|
|
49
|
+
# results MUST be logged and ignored, not raised. Force the polling
|
|
50
|
+
# resolver into log-and-continue mode regardless of caller options.
|
|
51
|
+
@resolver = Srv::Resolver.new(**opts, raise_on_invalid: false)
|
|
49
52
|
@last_result = @srv_uri.srv_result
|
|
50
53
|
@stop_semaphore = Semaphore.new
|
|
51
54
|
end
|
|
@@ -82,6 +85,12 @@ module Mongo
|
|
|
82
85
|
rescue Resolv::ResolvError => e
|
|
83
86
|
log_warn("SRV monitor: unable to resolve hostname #{@srv_uri.query_hostname}: #{e.class}: #{e}")
|
|
84
87
|
return
|
|
88
|
+
rescue Mongo::Error => e
|
|
89
|
+
# Defense in depth: the polling resolver is configured to log-and-continue
|
|
90
|
+
# for mismatched-domain and empty-result cases, but if any Mongo::Error
|
|
91
|
+
# leaks out we MUST NOT let it terminate the SRV monitor thread.
|
|
92
|
+
log_warn("SRV monitor: error resolving hostname #{@srv_uri.query_hostname}: #{e.class}: #{e}")
|
|
93
|
+
return
|
|
85
94
|
end
|
|
86
95
|
|
|
87
96
|
if last_result.empty?
|
data/lib/mongo/srv/resolver.rb
CHANGED
data/lib/mongo/srv/result.rb
CHANGED
|
@@ -123,9 +123,11 @@ module Mongo
|
|
|
123
123
|
raise Error::MismatchedDomain.new(format(MISMATCHED_DOMAINNAME, record_host, srv_host_domain))
|
|
124
124
|
end
|
|
125
125
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
126
|
+
record_matches_domain = (record_host_parts.size > srv_host_domain.size) &&
|
|
127
|
+
(srv_host_domain == record_host_parts[-srv_host_domain.size..-1])
|
|
128
|
+
return if record_matches_domain
|
|
129
|
+
|
|
130
|
+
raise Error::MismatchedDomain.new(format(MISMATCHED_DOMAINNAME, record_host, srv_host_domain))
|
|
129
131
|
end
|
|
130
132
|
end
|
|
131
133
|
end
|
data/lib/mongo/timeout.rb
CHANGED
|
@@ -18,8 +18,7 @@ module Mongo
|
|
|
18
18
|
# @api private
|
|
19
19
|
module Timeout
|
|
20
20
|
# A wrapper around Ruby core's Timeout::timeout method that provides
|
|
21
|
-
# a standardized API for
|
|
22
|
-
# which is when the third argument was introduced.
|
|
21
|
+
# a standardized API for calling it.
|
|
23
22
|
#
|
|
24
23
|
# @param [ Numeric ] sec The number of seconds before timeout.
|
|
25
24
|
# @param [ Class ] klass The exception class to raise on timeout, optional.
|
|
@@ -28,19 +27,15 @@ module Mongo
|
|
|
28
27
|
# on timeout, optional. When no error message is provided, the default
|
|
29
28
|
# error message for the exception class is used.
|
|
30
29
|
def timeout(sec, klass = nil, message = nil, &block)
|
|
31
|
-
if message
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
# Timeout::timeout method.
|
|
41
|
-
optional_args = [ klass, message ].compact
|
|
42
|
-
::Timeout.timeout(sec, *optional_args, &block)
|
|
43
|
-
end
|
|
30
|
+
# provide a default error class if the message is present; otherwise,
|
|
31
|
+
# the message will be interpreted as the error class, if klass is nil
|
|
32
|
+
klass ||= ::Timeout::Error if message
|
|
33
|
+
|
|
34
|
+
# Jruby Timeout::timeout method does not support passing nil arguments.
|
|
35
|
+
# Remove the nil arguments before passing them along to the core
|
|
36
|
+
# Timeout::timeout method.
|
|
37
|
+
optional_args = [ klass, message ].compact
|
|
38
|
+
::Timeout.timeout(sec, *optional_args, &block)
|
|
44
39
|
end
|
|
45
40
|
module_function :timeout
|
|
46
41
|
end
|
|
@@ -206,9 +206,23 @@ module Mongo
|
|
|
206
206
|
# @param _context [ OpenTelemetry::Context ] the context (unused).
|
|
207
207
|
# @param span [ OpenTelemetry::Trace::Span ] the current span.
|
|
208
208
|
def process_cursor_context(result, _cursor_id, _context, span)
|
|
209
|
-
|
|
209
|
+
cursor_id = normalize_cursor_id(result.cursor_id)
|
|
210
|
+
return unless cursor_id.positive?
|
|
210
211
|
|
|
211
|
-
span.set_attribute('db.mongodb.cursor_id',
|
|
212
|
+
span.set_attribute('db.mongodb.cursor_id', cursor_id)
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
# Normalizes a cursor id to a plain Integer.
|
|
216
|
+
#
|
|
217
|
+
# OP_MSG replies deserialized in :bson mode expose the cursor id as a
|
|
218
|
+
# BSON::Int64, which does not implement Numeric#positive? and is not a
|
|
219
|
+
# valid OpenTelemetry attribute type.
|
|
220
|
+
#
|
|
221
|
+
# @param cursor_id [ Integer | BSON::Int64 ] the raw cursor id.
|
|
222
|
+
#
|
|
223
|
+
# @return [ Integer ] the cursor id as an Integer.
|
|
224
|
+
def normalize_cursor_id(cursor_id)
|
|
225
|
+
cursor_id.is_a?(BSON::Int64) ? cursor_id.value : cursor_id
|
|
212
226
|
end
|
|
213
227
|
|
|
214
228
|
# Records error status code if the command failed.
|
|
@@ -87,7 +87,7 @@ module Mongo
|
|
|
87
87
|
strategy = URI_OPTION_MAP[key.downcase]
|
|
88
88
|
if strategy.nil?
|
|
89
89
|
log_warn("Unsupported URI option '#{key}' on URI '#{@string}'. It will be ignored.")
|
|
90
|
-
|
|
90
|
+
next
|
|
91
91
|
end
|
|
92
92
|
|
|
93
93
|
group = strategy[:group]
|
|
@@ -125,7 +125,7 @@ module Mongo
|
|
|
125
125
|
end
|
|
126
126
|
next if v.nil?
|
|
127
127
|
|
|
128
|
-
if type = spec[:type]
|
|
128
|
+
if (type = spec[:type])
|
|
129
129
|
v = send("revert_#{type}", v)
|
|
130
130
|
end
|
|
131
131
|
canonical_key = URI_OPTION_CANONICAL_NAMES[uri_key]
|
|
@@ -163,7 +163,7 @@ module Mongo
|
|
|
163
163
|
end
|
|
164
164
|
next if v.nil?
|
|
165
165
|
|
|
166
|
-
if type = spec[:type]
|
|
166
|
+
if (type = spec[:type])
|
|
167
167
|
v = send("stringify_#{type}", v)
|
|
168
168
|
end
|
|
169
169
|
canonical_key = URI_OPTION_CANONICAL_NAMES[uri_key]
|
|
@@ -354,13 +354,25 @@ module Mongo
|
|
|
354
354
|
|
|
355
355
|
# Converts the value into a boolean and returns it wrapped in an array.
|
|
356
356
|
#
|
|
357
|
-
#
|
|
357
|
+
# tls and ssl are the only repeated_bool options. An invalid value is
|
|
358
|
+
# preserved as a nil element rather than warned-and-dropped, so that
|
|
359
|
+
# URI#validate_uri_options! can detect it and raise instead of silently
|
|
360
|
+
# falling back to a plaintext connection (RUBY-3832).
|
|
361
|
+
#
|
|
362
|
+
# @param [ String ] _name Name of the URI option being processed.
|
|
358
363
|
# @param [ String ] value URI option value.
|
|
359
364
|
#
|
|
360
|
-
# @return [ Array<true | false
|
|
361
|
-
# in an array.
|
|
362
|
-
def convert_repeated_bool(
|
|
363
|
-
|
|
365
|
+
# @return [ Array<true | false | nil> ] The boolean value parsed and
|
|
366
|
+
# wrapped in an array.
|
|
367
|
+
def convert_repeated_bool(_name, value)
|
|
368
|
+
case value
|
|
369
|
+
when true, 'true', 'TRUE'
|
|
370
|
+
[ true ]
|
|
371
|
+
when false, 'false', 'FALSE'
|
|
372
|
+
[ false ]
|
|
373
|
+
else
|
|
374
|
+
[ nil ]
|
|
375
|
+
end
|
|
364
376
|
end
|
|
365
377
|
|
|
366
378
|
# Reverts a repeated boolean type.
|
|
@@ -379,7 +391,7 @@ module Mongo
|
|
|
379
391
|
# @return [ Array<true | false> | nil ] The string.
|
|
380
392
|
def stringify_repeated_bool(value)
|
|
381
393
|
rep = revert_repeated_bool(value)
|
|
382
|
-
if rep
|
|
394
|
+
if rep.is_a?(Array)
|
|
383
395
|
rep.join(',')
|
|
384
396
|
else
|
|
385
397
|
rep
|
|
@@ -117,14 +117,14 @@ module Mongo
|
|
|
117
117
|
raise Error::InvalidURI.new(@string, details, FORMAT)
|
|
118
118
|
end
|
|
119
119
|
|
|
120
|
-
# Gets the SRV resolver.
|
|
121
|
-
#
|
|
122
|
-
#
|
|
120
|
+
# Gets the SRV resolver used for initial URI parsing.
|
|
121
|
+
# Per the Initial DNS Seedlist Discovery spec, the driver MUST raise an
|
|
122
|
+
# error if domain verification fails or no SRV records are found, so
|
|
123
|
+
# raise_on_invalid is left at its default of true.
|
|
123
124
|
#
|
|
124
125
|
# @return [ Mongo::Srv::Resolver ]
|
|
125
126
|
def resolver
|
|
126
127
|
@resolver ||= Srv::Resolver.new(
|
|
127
|
-
raise_on_invalid: false,
|
|
128
128
|
resolv_options: options[:resolv_options],
|
|
129
129
|
timeout: options[:connect_timeout]
|
|
130
130
|
)
|
data/lib/mongo/uri.rb
CHANGED
|
@@ -141,6 +141,19 @@ module Mongo
|
|
|
141
141
|
# @since 2.5.0
|
|
142
142
|
SCHEME_DELIM = '://'
|
|
143
143
|
|
|
144
|
+
# Placeholder used in place of cleartext credentials when a URI is
|
|
145
|
+
# rendered for display, logging, or error reporting.
|
|
146
|
+
CREDENTIALS_PLACEHOLDER = '<credentials>'
|
|
147
|
+
|
|
148
|
+
# Pattern matching the userinfo portion of a MongoDB connection string.
|
|
149
|
+
# Anchors at the start and is bounded to the authority component (stops at
|
|
150
|
+
# the first '/', '?', or '#'), but matches greedily up to the last '@' in
|
|
151
|
+
# that component so passwords containing an unescaped '@' are still fully
|
|
152
|
+
# redacted. Case-insensitive so an unusual scheme like 'MongoDB://' is
|
|
153
|
+
# redacted too — the parser will reject it, and the redactor must not be
|
|
154
|
+
# the thing that leaks the credentials in the resulting error.
|
|
155
|
+
USERINFO_REDACTION_REGEX = %r{\A(mongodb(?:\+srv)?://)[^/?#]*@}i.freeze
|
|
156
|
+
|
|
144
157
|
# Error details for an invalid options format.
|
|
145
158
|
#
|
|
146
159
|
# @since 2.1.0
|
|
@@ -215,6 +228,24 @@ module Mongo
|
|
|
215
228
|
# @since 2.1.0
|
|
216
229
|
REPEATABLE_OPTIONS = %i[tag_sets ssl]
|
|
217
230
|
|
|
231
|
+
# Replace the userinfo portion of a MongoDB connection string with a
|
|
232
|
+
# placeholder so the result can safely be logged, displayed, or embedded
|
|
233
|
+
# in an exception message.
|
|
234
|
+
#
|
|
235
|
+
# The input is matched as a string, not parsed, so this is safe to call
|
|
236
|
+
# on malformed URIs (which is exactly when {InvalidURI} is raised).
|
|
237
|
+
#
|
|
238
|
+
# @param [ String ] string The raw URI string.
|
|
239
|
+
#
|
|
240
|
+
# @return [ String ] The URI with any userinfo replaced by
|
|
241
|
+
# {CREDENTIALS_PLACEHOLDER}, or the input unchanged if it is not a
|
|
242
|
+
# string or has no userinfo.
|
|
243
|
+
def self.redact(string)
|
|
244
|
+
return string unless string.is_a?(String)
|
|
245
|
+
|
|
246
|
+
string.sub(USERINFO_REDACTION_REGEX, "\\1#{CREDENTIALS_PLACEHOLDER}@")
|
|
247
|
+
end
|
|
248
|
+
|
|
218
249
|
# Get either a URI object or a SRVProtocol URI object.
|
|
219
250
|
#
|
|
220
251
|
# @example Get the uri object.
|
|
@@ -320,20 +351,33 @@ module Mongo
|
|
|
320
351
|
@database || Database::ADMIN
|
|
321
352
|
end
|
|
322
353
|
|
|
323
|
-
# Get the uri as a string.
|
|
354
|
+
# Get the uri as a string with any credentials redacted.
|
|
355
|
+
#
|
|
356
|
+
# Credentials are replaced with {CREDENTIALS_PLACEHOLDER} so the result is
|
|
357
|
+
# safe to log or display. Use {#credentials} to recover the original user
|
|
358
|
+
# and password.
|
|
324
359
|
#
|
|
325
360
|
# @example Get the uri as a string.
|
|
326
361
|
# uri.to_s
|
|
327
362
|
#
|
|
328
|
-
# @return [ String ] The uri string.
|
|
363
|
+
# @return [ String ] The redacted uri string.
|
|
329
364
|
def to_s
|
|
330
365
|
reconstruct_uri
|
|
331
366
|
end
|
|
332
367
|
|
|
368
|
+
# Return a redacted, human-readable representation of the URI. The
|
|
369
|
+
# default {Object#inspect} would dump {@string} and {@password} as
|
|
370
|
+
# instance variables, leaking credentials.
|
|
371
|
+
#
|
|
372
|
+
# @return [ String ] The redacted inspect string.
|
|
373
|
+
def inspect
|
|
374
|
+
"#<#{self.class.name}: #{reconstruct_uri}>"
|
|
375
|
+
end
|
|
376
|
+
|
|
333
377
|
private
|
|
334
378
|
|
|
335
|
-
# Reconstruct the URI from its parts
|
|
336
|
-
# are converted to camelCase.
|
|
379
|
+
# Reconstruct the URI from its parts with credentials redacted. Invalid
|
|
380
|
+
# options are dropped and options are converted to camelCase.
|
|
337
381
|
#
|
|
338
382
|
# @return [ String ] the uri.
|
|
339
383
|
def reconstruct_uri
|
|
@@ -349,9 +393,7 @@ module Mongo
|
|
|
349
393
|
end.compact.join('&')
|
|
350
394
|
|
|
351
395
|
uri = "#{scheme}#{SCHEME_DELIM}"
|
|
352
|
-
uri += @
|
|
353
|
-
uri += "#{AUTH_USER_PWD_DELIM}#{@password}" if @password
|
|
354
|
-
uri += '@' if @user || @password
|
|
396
|
+
uri += "#{CREDENTIALS_PLACEHOLDER}@" if @user || @password
|
|
355
397
|
uri += @query_hostname || servers
|
|
356
398
|
uri += '/' if @database || !options.empty?
|
|
357
399
|
uri += @database.to_s if @database
|
|
@@ -418,7 +460,7 @@ module Mongo
|
|
|
418
460
|
end
|
|
419
461
|
|
|
420
462
|
def parse_user!(string)
|
|
421
|
-
if string && user = string.partition(AUTH_USER_PWD_DELIM)[0]
|
|
463
|
+
if string && (user = string.partition(AUTH_USER_PWD_DELIM)[0])
|
|
422
464
|
raise_invalid_error!(UNESCAPED_USER_PWD) if UNSAFE.match?(user)
|
|
423
465
|
user_decoded = decode(user)
|
|
424
466
|
raise_invalid_error!(UNESCAPED_USER_PWD) if user_decoded =~ PERCENT_CHAR && encode(user_decoded) != user
|
|
@@ -461,6 +503,12 @@ module Mongo
|
|
|
461
503
|
# 'tls' and 'ssl'. In order to fulfill this, we parse the values of each instance into an
|
|
462
504
|
# array; assuming all values in the array are the same, we replace the array with that value.
|
|
463
505
|
unless uri_options[:ssl].nil? || uri_options[:ssl].empty?
|
|
506
|
+
# A nil element means an invalid value (e.g. tls=yes) was supplied.
|
|
507
|
+
# Refuse it rather than silently connecting over plaintext (RUBY-3832).
|
|
508
|
+
if uri_options[:ssl].include?(nil)
|
|
509
|
+
raise_invalid_error_no_fmt!("invalid boolean value for 'tls' or 'ssl'; only 'true' and 'false' are accepted")
|
|
510
|
+
end
|
|
511
|
+
|
|
464
512
|
unless uri_options[:ssl].uniq.length == 1
|
|
465
513
|
raise_invalid_error_no_fmt!("all instances of 'tls' and 'ssl' must have the same value")
|
|
466
514
|
end
|
data/lib/mongo/utils.rb
CHANGED
|
@@ -73,7 +73,7 @@ module Mongo
|
|
|
73
73
|
# @note server_api must have symbol keys or be a BSON::Document.
|
|
74
74
|
module_function def transform_server_api(server_api)
|
|
75
75
|
{}.tap do |doc|
|
|
76
|
-
if version = server_api[:version]
|
|
76
|
+
if (version = server_api[:version])
|
|
77
77
|
doc['apiVersion'] = version
|
|
78
78
|
end
|
|
79
79
|
doc['apiStrict'] = server_api[:strict] unless server_api[:strict].nil?
|
data/lib/mongo/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: mongo
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.25.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- The MongoDB Ruby Team
|
|
@@ -90,8 +90,6 @@ files:
|
|
|
90
90
|
- lib/mongo/auth/stringprep.rb
|
|
91
91
|
- lib/mongo/auth/stringprep/profiles/sasl.rb
|
|
92
92
|
- lib/mongo/auth/stringprep/tables.rb
|
|
93
|
-
- lib/mongo/auth/stringprep/unicode_normalize/normalize.rb
|
|
94
|
-
- lib/mongo/auth/stringprep/unicode_normalize/tables.rb
|
|
95
93
|
- lib/mongo/auth/user.rb
|
|
96
94
|
- lib/mongo/auth/user/view.rb
|
|
97
95
|
- lib/mongo/auth/x509.rb
|
|
@@ -191,6 +189,7 @@ files:
|
|
|
191
189
|
- lib/mongo/cursor/nontailable.rb
|
|
192
190
|
- lib/mongo/cursor_host.rb
|
|
193
191
|
- lib/mongo/database.rb
|
|
192
|
+
- lib/mongo/database/cursor_command_view.rb
|
|
194
193
|
- lib/mongo/database/view.rb
|
|
195
194
|
- lib/mongo/dbref.rb
|
|
196
195
|
- lib/mongo/deprecations.rb
|
|
@@ -369,6 +368,9 @@ files:
|
|
|
369
368
|
- lib/mongo/operation/create_search_indexes/op_msg.rb
|
|
370
369
|
- lib/mongo/operation/create_user.rb
|
|
371
370
|
- lib/mongo/operation/create_user/op_msg.rb
|
|
371
|
+
- lib/mongo/operation/cursor_command.rb
|
|
372
|
+
- lib/mongo/operation/cursor_command/op_msg.rb
|
|
373
|
+
- lib/mongo/operation/cursor_command/result.rb
|
|
372
374
|
- lib/mongo/operation/delete.rb
|
|
373
375
|
- lib/mongo/operation/delete/bulk_result.rb
|
|
374
376
|
- lib/mongo/operation/delete/op_msg.rb
|
|
@@ -559,7 +561,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
559
561
|
- !ruby/object:Gem::Version
|
|
560
562
|
version: '0'
|
|
561
563
|
requirements: []
|
|
562
|
-
rubygems_version: 4.0.
|
|
564
|
+
rubygems_version: 4.0.17
|
|
563
565
|
specification_version: 4
|
|
564
566
|
summary: Ruby driver for MongoDB
|
|
565
567
|
test_files: []
|