mongo 2.10.5 → 2.11.0.rc0
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 +0 -0
- data/CONTRIBUTING.md +1 -1
- data/lib/mongo.rb +2 -0
- data/lib/mongo/address.rb +4 -0
- data/lib/mongo/address/validator.rb +99 -0
- data/lib/mongo/auth.rb +7 -2
- data/lib/mongo/auth/user.rb +1 -7
- data/lib/mongo/background_thread.rb +135 -0
- data/lib/mongo/bulk_write/transformable.rb +3 -3
- data/lib/mongo/client.rb +74 -16
- data/lib/mongo/cluster.rb +193 -41
- data/lib/mongo/cluster/periodic_executor.rb +31 -43
- data/lib/mongo/cluster/sdam_flow.rb +26 -3
- data/lib/mongo/cluster/srv_monitor.rb +127 -0
- data/lib/mongo/collection/view/readable.rb +3 -5
- data/lib/mongo/collection/view/writable.rb +3 -3
- data/lib/mongo/cursor/builder/get_more_command.rb +1 -4
- data/lib/mongo/cursor/builder/kill_cursors_command.rb +5 -23
- data/lib/mongo/cursor/builder/op_get_more.rb +2 -2
- data/lib/mongo/cursor/builder/op_kill_cursors.rb +5 -24
- data/lib/mongo/error.rb +1 -0
- data/lib/mongo/error/auth_error.rb +1 -1
- data/lib/mongo/error/connection_check_out_timeout.rb +7 -8
- data/lib/mongo/error/invalid_address.rb +24 -0
- data/lib/mongo/error/notable.rb +2 -2
- data/lib/mongo/error/operation_failure.rb +3 -3
- data/lib/mongo/error/pool_closed_error.rb +11 -4
- data/lib/mongo/event.rb +1 -1
- data/lib/mongo/grid/file.rb +0 -5
- data/lib/mongo/grid/file/chunk.rb +0 -2
- data/lib/mongo/grid/fs_bucket.rb +13 -15
- data/lib/mongo/grid/stream/write.rb +3 -9
- data/lib/mongo/loggable.rb +5 -1
- data/lib/mongo/monitoring.rb +1 -0
- data/lib/mongo/monitoring/event/cmap/connection_check_out_failed.rb +7 -0
- data/lib/mongo/monitoring/event/cmap/connection_checked_in.rb +11 -3
- data/lib/mongo/monitoring/event/cmap/connection_checked_out.rb +11 -3
- data/lib/mongo/monitoring/event/cmap/pool_closed.rb +11 -3
- data/lib/mongo/monitoring/event/cmap/pool_created.rb +12 -3
- data/lib/mongo/monitoring/unified_sdam_log_subscriber.rb +62 -0
- data/lib/mongo/operation/shared/executable.rb +5 -10
- data/lib/mongo/operation/shared/sessions_supported.rb +1 -5
- data/lib/mongo/protocol/get_more.rb +1 -2
- data/lib/mongo/protocol/kill_cursors.rb +13 -6
- data/lib/mongo/protocol/serializers.rb +4 -20
- data/lib/mongo/retryable.rb +9 -34
- data/lib/mongo/semaphore.rb +1 -1
- data/lib/mongo/server.rb +113 -42
- data/lib/mongo/server/connection.rb +12 -5
- data/lib/mongo/server/connection_pool.rb +250 -40
- data/lib/mongo/server/connection_pool/populator.rb +58 -0
- data/lib/mongo/server/description.rb +9 -2
- data/lib/mongo/server/monitor.rb +68 -93
- data/lib/mongo/server/monitor/connection.rb +2 -0
- data/lib/mongo/server_selector/selectable.rb +13 -5
- data/lib/mongo/session.rb +0 -13
- data/lib/mongo/srv.rb +17 -0
- data/lib/mongo/srv/monitor.rb +96 -0
- data/lib/mongo/srv/resolver.rb +130 -0
- data/lib/mongo/srv/result.rb +126 -0
- data/lib/mongo/srv/warning_result.rb +35 -0
- data/lib/mongo/uri.rb +45 -55
- data/lib/mongo/uri/srv_protocol.rb +89 -42
- data/lib/mongo/version.rb +1 -1
- data/mongo.gemspec +3 -4
- data/spec/README.md +6 -1
- data/spec/enterprise_auth/kerberos_spec.rb +7 -6
- data/spec/integration/change_stream_examples_spec.rb +0 -4
- data/spec/integration/client_construction_spec.rb +14 -2
- data/spec/integration/connect_single_rs_name_spec.rb +2 -2
- data/spec/integration/connection_pool_populator_spec.rb +296 -0
- data/spec/integration/connection_spec.rb +31 -22
- data/spec/integration/cursor_reaping_spec.rb +1 -2
- data/spec/integration/docs_examples_spec.rb +0 -4
- data/spec/integration/heartbeat_events_spec.rb +17 -15
- data/spec/integration/reconnect_spec.rb +144 -1
- data/spec/integration/retryable_writes_errors_spec.rb +0 -4
- data/spec/integration/retryable_writes_spec.rb +36 -36
- data/spec/integration/sdam_error_handling_spec.rb +31 -25
- data/spec/integration/sdam_events_spec.rb +2 -6
- data/spec/integration/server_monitor_spec.rb +28 -0
- data/spec/integration/server_selector_spec.rb +7 -5
- data/spec/integration/srv_monitoring_spec.rb +360 -0
- data/spec/integration/step_down_spec.rb +4 -6
- data/spec/lite_spec_helper.rb +22 -0
- data/spec/mongo/address/validator_spec.rb +51 -0
- data/spec/mongo/auth/cr_spec.rb +1 -29
- data/spec/mongo/auth/ldap_spec.rb +1 -29
- data/spec/mongo/auth/scram/conversation_spec.rb +0 -2
- data/spec/mongo/auth/scram/negotiation_spec.rb +1 -1
- data/spec/mongo/auth/scram_spec.rb +1 -29
- data/spec/mongo/auth/user/view_spec.rb +1 -36
- data/spec/mongo/auth/user_spec.rb +0 -12
- data/spec/mongo/auth/x509_spec.rb +1 -29
- data/spec/mongo/bulk_write_spec.rb +2 -2
- data/spec/mongo/client_construction_spec.rb +56 -15
- data/spec/mongo/client_spec.rb +31 -27
- data/spec/mongo/cluster/periodic_executor_spec.rb +16 -0
- data/spec/mongo/cluster/srv_monitor_spec.rb +214 -0
- data/spec/mongo/cluster/topology/replica_set_spec.rb +16 -11
- data/spec/mongo/cluster/topology/sharded_spec.rb +12 -9
- data/spec/mongo/cluster/topology/single_spec.rb +20 -11
- data/spec/mongo/cluster_spec.rb +45 -29
- data/spec/mongo/collection/view/map_reduce_spec.rb +14 -9
- data/spec/mongo/collection/view/readable_spec.rb +0 -16
- data/spec/mongo/collection_spec.rb +0 -44
- data/spec/mongo/cursor/builder/get_more_command_spec.rb +2 -4
- data/spec/mongo/cursor/builder/op_get_more_spec.rb +2 -4
- data/spec/mongo/cursor_spec.rb +27 -7
- data/spec/mongo/monitoring/event/cmap/connection_checked_in_spec.rb +10 -3
- data/spec/mongo/monitoring/event/cmap/connection_checked_out_spec.rb +10 -3
- data/spec/mongo/monitoring/event/cmap/pool_closed_spec.rb +10 -3
- data/spec/mongo/monitoring/event/cmap/pool_created_spec.rb +10 -3
- data/spec/mongo/operation/delete/op_msg_spec.rb +17 -8
- data/spec/mongo/operation/insert/op_msg_spec.rb +50 -35
- data/spec/mongo/operation/update/op_msg_spec.rb +14 -7
- data/spec/mongo/retryable_spec.rb +52 -31
- data/spec/mongo/server/app_metadata_spec.rb +0 -8
- data/spec/mongo/server/connection_auth_spec.rb +5 -2
- data/spec/mongo/server/connection_pool/populator_spec.rb +101 -0
- data/spec/mongo/server/connection_pool_spec.rb +256 -107
- data/spec/mongo/server/connection_spec.rb +22 -33
- data/spec/mongo/server/description_spec.rb +42 -4
- data/spec/mongo/server/monitor/connection_spec.rb +22 -11
- data/spec/mongo/server/monitor_spec.rb +66 -107
- data/spec/mongo/server_spec.rb +82 -60
- data/spec/mongo/session/session_pool_spec.rb +1 -5
- data/spec/mongo/session_spec.rb +0 -4
- data/spec/mongo/socket/ssl_spec.rb +2 -2
- data/spec/mongo/srv/monitor_spec.rb +211 -0
- data/spec/mongo/srv/result_spec.rb +54 -0
- data/spec/mongo/uri/srv_protocol_spec.rb +30 -15
- data/spec/mongo/uri_spec.rb +125 -4
- data/spec/spec_helper.rb +6 -0
- data/spec/spec_tests/auth_spec.rb +39 -0
- data/spec/spec_tests/cmap_spec.rb +55 -8
- data/spec/spec_tests/connection_string_spec.rb +6 -31
- data/spec/spec_tests/data/auth/connection-string.yml +297 -0
- data/spec/spec_tests/data/cmap/pool-checkout-error-closed.yml +4 -1
- data/spec/spec_tests/data/cmap/pool-create-with-options.yml +1 -0
- data/spec/spec_tests/data/command_monitoring/insertMany.yml +1 -1
- data/spec/spec_tests/data/connection_string/invalid-uris.yml +20 -0
- data/spec/spec_tests/data/connection_string/valid-auth.yml +16 -0
- data/spec/spec_tests/data/connection_string/valid-warnings.yml +26 -30
- data/spec/spec_tests/data/transactions/abort.yml +3 -3
- data/spec/spec_tests/data/transactions/error-labels.yml +3 -3
- data/spec/spec_tests/data/transactions_api/callback-retry.yml +3 -3
- data/spec/spec_tests/data/uri_options/auth-options.yml +1 -1
- data/spec/spec_tests/max_staleness_spec.rb +7 -2
- data/spec/spec_tests/retryable_reads_spec.rb +0 -31
- data/spec/spec_tests/sdam_monitoring_spec.rb +12 -12
- data/spec/spec_tests/sdam_spec.rb +4 -7
- data/spec/spec_tests/server_selection_spec.rb +6 -2
- data/spec/spec_tests/transactions_spec.rb +0 -2
- data/spec/spec_tests/uri_options_spec.rb +4 -2
- data/spec/stress/connection_pool_stress_spec.rb +203 -0
- data/spec/stress/connection_pool_timing_spec.rb +181 -0
- data/spec/support/auth.rb +113 -0
- data/spec/support/background_thread_registry.rb +63 -0
- data/spec/support/client_registry.rb +11 -2
- data/spec/support/cluster_config.rb +65 -46
- data/spec/support/cluster_tools.rb +2 -2
- data/spec/support/cmap.rb +13 -14
- data/spec/support/cmap/verifier.rb +4 -5
- data/spec/support/command_monitoring.rb +0 -5
- data/spec/support/common_shortcuts.rb +101 -1
- data/spec/support/constraints.rb +25 -0
- data/spec/support/dns.rb +13 -0
- data/spec/support/event_subscriber.rb +0 -7
- data/spec/support/json_ext_formatter.rb +5 -1
- data/spec/support/lite_constraints.rb +22 -6
- data/spec/support/local_resource_registry.rb +34 -0
- data/spec/support/sdam_monitoring.rb +115 -0
- data/spec/support/spec_config.rb +20 -6
- data/spec/support/spec_setup.rb +2 -2
- data/spec/support/transactions.rb +1 -1
- data/spec/support/transactions/test.rb +1 -1
- data/spec/support/utils.rb +1 -16
- metadata +685 -659
- metadata.gz.sig +0 -0
- data/lib/mongo/event/description_changed.rb +0 -52
- data/spec/integration/bson_symbol_spec.rb +0 -34
- data/spec/integration/crud_spec.rb +0 -45
- data/spec/integration/get_more_spec.rb +0 -32
- data/spec/integration/grid_fs_bucket_spec.rb +0 -48
- data/spec/integration/retryable_errors_spec.rb +0 -265
- data/spec/integration/size_limit_spec.rb~12e1e9c4f... RUBY-2242 Fix zlib compression (#2021) +0 -98
- data/spec/mongo/cursor/builder/op_kill_cursors_spec.rb +0 -56
- data/spec/runners/sdam/verifier.rb +0 -88
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b7c88c591ffb30fe10134db69727372a4d1c3801a11dce59804ebe53d475d08f
|
4
|
+
data.tar.gz: 16ce4f803cd46df9e0bc6948048fc4c0ea5356d437fbf75b149d38cd872ccca1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eb30b7789af0a8816ce50e4b5c3be68e0b0a6f3a0b2da8d4c13a6f6bc8ad826b6a6b505e99df369ed49b24543baa28ff08db655ce3701c1fd2f13b55d4bb9374
|
7
|
+
data.tar.gz: 7490c21d89f2b2c88aaa69d8203973869c409c637c0a212cb2d3cd2783ca258cd6a2df6729375e39894303b39541fd0296faee7c691d1b3e4c3553f6c6169385
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/CONTRIBUTING.md
CHANGED
@@ -23,7 +23,7 @@ Environment
|
|
23
23
|
We recommend using [rbenv](https://github.com/sstephenson/rbenv) to set up
|
24
24
|
the Ruby development and testing environments, though other tools like
|
25
25
|
[RVM](https://rvm.io/) will also work. The driver currently supports
|
26
|
-
MRI
|
26
|
+
MRI 2.3-2.6 and JRuby 9.2.
|
27
27
|
|
28
28
|
A MongoDB cluster is required to run the tests. Setup procedures and
|
29
29
|
recommendations for various clusters, as well as how to configure the
|
data/lib/mongo.rb
CHANGED
@@ -44,6 +44,7 @@ require 'mongo/event'
|
|
44
44
|
require 'mongo/address'
|
45
45
|
require 'mongo/auth'
|
46
46
|
require 'mongo/protocol'
|
47
|
+
require 'mongo/background_thread'
|
47
48
|
require 'mongo/cluster'
|
48
49
|
require 'mongo/cursor'
|
49
50
|
require 'mongo/collection'
|
@@ -56,6 +57,7 @@ require 'mongo/server'
|
|
56
57
|
require 'mongo/server_selector'
|
57
58
|
require 'mongo/session'
|
58
59
|
require 'mongo/socket'
|
60
|
+
require 'mongo/srv'
|
59
61
|
require 'mongo/uri'
|
60
62
|
require 'mongo/version'
|
61
63
|
require 'mongo/write_concern'
|
data/lib/mongo/address.rb
CHANGED
@@ -15,6 +15,7 @@
|
|
15
15
|
require 'mongo/address/ipv4'
|
16
16
|
require 'mongo/address/ipv6'
|
17
17
|
require 'mongo/address/unix'
|
18
|
+
require 'mongo/address/validator'
|
18
19
|
|
19
20
|
module Mongo
|
20
21
|
|
@@ -67,6 +68,9 @@ module Mongo
|
|
67
68
|
#
|
68
69
|
# @since 2.0.0
|
69
70
|
def initialize(seed, options = {})
|
71
|
+
if seed.nil?
|
72
|
+
raise ArgumentError, "address must be not nil"
|
73
|
+
end
|
70
74
|
@seed = seed
|
71
75
|
@host, @port = parse_host_port
|
72
76
|
@options = options
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# Copyright (C) 2017-2019 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
|
+
|
17
|
+
class Address
|
18
|
+
|
19
|
+
# @api private
|
20
|
+
module Validator
|
21
|
+
|
22
|
+
# Takes an address string in ipv4/ipv6/hostname/socket path format and
|
23
|
+
# validates its format.
|
24
|
+
def validate_address_str!(address_str)
|
25
|
+
case address_str
|
26
|
+
when /\A\[[\d:]+\](?::(\d+))?\z/
|
27
|
+
# ipv6 with optional port
|
28
|
+
if port_str = $1
|
29
|
+
validate_port_str!(port_str)
|
30
|
+
end
|
31
|
+
when /\A\//, /\.sock\z/
|
32
|
+
# Unix socket path.
|
33
|
+
# Spec requires us to validate that the path has no unescaped
|
34
|
+
# slashes, but if this were to be the case, parsing would have
|
35
|
+
# already failed elsewhere because the URI would've been split in
|
36
|
+
# a weird place.
|
37
|
+
# The spec also allows relative socket paths and requires that
|
38
|
+
# socket paths end in ".sock". We accept all paths but special case
|
39
|
+
# the .sock extension to avoid relative paths falling into the
|
40
|
+
# host:port case below.
|
41
|
+
when /[\/\[\]]/
|
42
|
+
# Not a host:port nor an ipv4 address with optional port.
|
43
|
+
# Possibly botched ipv6 address with e.g. port delimiter present and
|
44
|
+
# port missing, or extra junk before or after.
|
45
|
+
raise Error::InvalidAddress,
|
46
|
+
"Invalid hostname: #{address_str}"
|
47
|
+
when /:.*:/m
|
48
|
+
raise Error::InvalidAddress,
|
49
|
+
"Multiple port delimiters are not allowed: #{address_str}"
|
50
|
+
else
|
51
|
+
# host:port or ipv4 address with optional port number
|
52
|
+
host, port = address_str.split(':')
|
53
|
+
if host.empty?
|
54
|
+
raise Error::InvalidAddress, "Host is empty: #{address_str}"
|
55
|
+
end
|
56
|
+
|
57
|
+
validate_hostname!(host)
|
58
|
+
|
59
|
+
if port && port.empty?
|
60
|
+
raise Error::InvalidAddress, "Port is empty: #{address_str}"
|
61
|
+
end
|
62
|
+
|
63
|
+
validate_port_str!(port)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
# Validates format of the hostname, in particular for further use as
|
70
|
+
# the origin in same origin verification.
|
71
|
+
#
|
72
|
+
# The hostname must have been normalized to remove the trailing dot if
|
73
|
+
# it was obtained from a DNS record. This method prohibits trailing dots.
|
74
|
+
def validate_hostname!(host)
|
75
|
+
# Since we are performing same origin verification during SRV
|
76
|
+
# processing, prohibit leading dots in hostnames, trailing dots
|
77
|
+
# and runs of multiple dots. DNS resolution of SRV records yields
|
78
|
+
# hostnames with trailing dots, those trailing dots are removed
|
79
|
+
# during normalization process prior to validation.
|
80
|
+
if host.start_with?('.')
|
81
|
+
raise Error::InvalidAddress, "Hostname cannot start with a dot: #{host}"
|
82
|
+
end
|
83
|
+
if host.end_with?('.')
|
84
|
+
raise Error::InvalidAddress, "Hostname cannot end with a dot: #{host}"
|
85
|
+
end
|
86
|
+
if host.include?('..')
|
87
|
+
raise Error::InvalidAddress, "Runs of multiple dots are not allowed in hostname: #{host}"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def validate_port_str!(port)
|
92
|
+
unless port.nil? || (port.length > 0 && port.to_i > 0 && port.to_i <= 65535)
|
93
|
+
raise Error::InvalidAddress,
|
94
|
+
"Invalid port: #{port}. Port must be an integer greater than 0 and less than 65536"
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
data/lib/mongo/auth.rb
CHANGED
@@ -70,10 +70,15 @@ module Mongo
|
|
70
70
|
SOURCES[mechanism].new(user)
|
71
71
|
end
|
72
72
|
|
73
|
+
# Raised when trying to authorize with an invalid configuration
|
74
|
+
#
|
75
|
+
# @since 2.11.0
|
76
|
+
class InvalidConfiguration < Mongo::Error::AuthError; end
|
77
|
+
|
73
78
|
# Raised when trying to get an invalid authorization mechanism.
|
74
79
|
#
|
75
80
|
# @since 2.0.0
|
76
|
-
class InvalidMechanism <
|
81
|
+
class InvalidMechanism < InvalidConfiguration
|
77
82
|
|
78
83
|
# Instantiate the new error.
|
79
84
|
#
|
@@ -94,7 +99,7 @@ module Mongo
|
|
94
99
|
# Raised when a user is not authorized on a database.
|
95
100
|
#
|
96
101
|
# @since 2.0.0
|
97
|
-
class Unauthorized <
|
102
|
+
class Unauthorized < Mongo::Error::AuthError
|
98
103
|
|
99
104
|
# Instantiate the new error.
|
100
105
|
#
|
data/lib/mongo/auth/user.rb
CHANGED
@@ -151,8 +151,6 @@ module Mongo
|
|
151
151
|
# authorized for.
|
152
152
|
# @option options [ String ] :user The user name.
|
153
153
|
# @option options [ String ] :password The user's password.
|
154
|
-
# @option options [ String ] :pwd Legacy option for the user's password.
|
155
|
-
# If :password and :pwd are both specified, :password takes precedence.
|
156
154
|
# @option options [ Symbol ] :auth_mech The authorization mechanism.
|
157
155
|
# @option options [ Array<String>, Array<Hash> ] roles The user roles.
|
158
156
|
# @option options [ String ] :client_key The user's client key cached from a previous
|
@@ -198,11 +196,7 @@ module Mongo
|
|
198
196
|
#
|
199
197
|
# @since 2.0.0
|
200
198
|
def spec
|
201
|
-
{roles: roles}
|
202
|
-
if password
|
203
|
-
spec[:pwd] = password
|
204
|
-
end
|
205
|
-
end
|
199
|
+
{ pwd: password, roles: roles }
|
206
200
|
end
|
207
201
|
|
208
202
|
private
|
@@ -0,0 +1,135 @@
|
|
1
|
+
# Copyright (C) 2019 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
|
+
|
17
|
+
# The run!, running? and stop! methods used to be part of the public API
|
18
|
+
# in some of the classes which now include this module. Therefore these
|
19
|
+
# methods must be considered part of the driver's public API for backwards
|
20
|
+
# compatibility reasons. However using these methods outside of the driver
|
21
|
+
# is deprecated.
|
22
|
+
#
|
23
|
+
# @api private
|
24
|
+
module BackgroundThread
|
25
|
+
include Loggable
|
26
|
+
|
27
|
+
# Start the background thread.
|
28
|
+
#
|
29
|
+
# If the thread is already running, this method does nothing.
|
30
|
+
#
|
31
|
+
# @api public for backwards compatibility only
|
32
|
+
def run!
|
33
|
+
if running?
|
34
|
+
@thread
|
35
|
+
else
|
36
|
+
start!
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# @api public for backwards compatibility only
|
41
|
+
def running?
|
42
|
+
if @thread
|
43
|
+
@thread.alive?
|
44
|
+
else
|
45
|
+
false
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Stop the background thread and wait for to terminate for a reasonable
|
50
|
+
# amount of time.
|
51
|
+
#
|
52
|
+
# @return [ true | false ] Whether the thread was terminated.
|
53
|
+
#
|
54
|
+
# @api public for backwards compatibility only
|
55
|
+
def stop!
|
56
|
+
# If the thread was not started, there is nothing to stop.
|
57
|
+
#
|
58
|
+
# Classes including this module may want to perform additional
|
59
|
+
# cleanup, which they can do by overriding this method.
|
60
|
+
return true unless @thread
|
61
|
+
|
62
|
+
# Background threads generally perform operations in a loop.
|
63
|
+
# This flag is meant to be checked on each iteration of the
|
64
|
+
# working loops and the thread should stop working when this flag
|
65
|
+
# is set.
|
66
|
+
@stop_requested = true
|
67
|
+
|
68
|
+
# Besides setting the flag, a particular class may have additional
|
69
|
+
# ways of signaling the background thread to either stop working or
|
70
|
+
# wake up to check the stop flag, for example, setting a semaphore.
|
71
|
+
# This can be accomplished by providing the pre_stop method.
|
72
|
+
pre_stop
|
73
|
+
|
74
|
+
# Now we have requested the graceful termination, and we could wait
|
75
|
+
# for the thread to exit on its own accord. A future version of the
|
76
|
+
# driver may allow a certain amount of time for the thread to quit.
|
77
|
+
# For now, we additionally use the Ruby machinery to request the thread
|
78
|
+
# be terminated, and do so immediately.
|
79
|
+
#
|
80
|
+
# Note that this may cause the background thread to terminate in
|
81
|
+
# the middle of an operation.
|
82
|
+
@thread.kill
|
83
|
+
|
84
|
+
# Wait for the thread to die. This is important in order to reliably
|
85
|
+
# clean up resources like connections knowing that no background
|
86
|
+
# thread will reconnect because it is still working.
|
87
|
+
#
|
88
|
+
# However, we do not want to wait indefinitely because in theory
|
89
|
+
# a background thread could be performing, say, network I/O and if
|
90
|
+
# the network is no longer available that could take a long time.
|
91
|
+
start_time = Time.now
|
92
|
+
([0.1, 0.15] + [0.2] * 5 + [0.3] * 20).each do |interval|
|
93
|
+
begin
|
94
|
+
Timeout.timeout(interval) do
|
95
|
+
@thread.join
|
96
|
+
end
|
97
|
+
break
|
98
|
+
rescue Timeout::Error
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# Some driver objects can be reconnected, for backwards compatibiilty
|
103
|
+
# reasons. Clear the thread instance variable to support this cleanly.
|
104
|
+
if @thread.alive?
|
105
|
+
log_warn("Failed to stop background thread in #{self} in #{(Time.now - start_time).to_i} seconds")
|
106
|
+
false
|
107
|
+
else
|
108
|
+
@thread = nil
|
109
|
+
true
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
private
|
114
|
+
|
115
|
+
# @return [ Thread ] The created Thread instance.
|
116
|
+
def start!
|
117
|
+
@thread = Thread.new do
|
118
|
+
catch(:done) do
|
119
|
+
until @stop_requested
|
120
|
+
do_work
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
# Override this method to do the work in the background thread.
|
127
|
+
def do_work
|
128
|
+
end
|
129
|
+
|
130
|
+
# Override this method to perform additional signaling for the background
|
131
|
+
# thread to stop.
|
132
|
+
def pre_stop
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
@@ -92,7 +92,7 @@ module Mongo
|
|
92
92
|
Operation::U => doc[:replacement],
|
93
93
|
}.tap do |d|
|
94
94
|
if doc[:upsert]
|
95
|
-
d[
|
95
|
+
d[:upsert] = true
|
96
96
|
end
|
97
97
|
d[Operation::COLLATION] = doc[:collation] if doc[:collation]
|
98
98
|
end
|
@@ -108,7 +108,7 @@ module Mongo
|
|
108
108
|
Operation::MULTI => true,
|
109
109
|
}.tap do |d|
|
110
110
|
if doc[:upsert]
|
111
|
-
d[
|
111
|
+
d[:upsert] = true
|
112
112
|
end
|
113
113
|
d[Operation::COLLATION] = doc[:collation] if doc[:collation]
|
114
114
|
d[Operation::ARRAY_FILTERS] = doc[:array_filters] if doc[:array_filters]
|
@@ -124,7 +124,7 @@ module Mongo
|
|
124
124
|
Operation::U => doc[:update],
|
125
125
|
}.tap do |d|
|
126
126
|
if doc[:upsert]
|
127
|
-
d[
|
127
|
+
d[:upsert] = true
|
128
128
|
end
|
129
129
|
d[Operation::COLLATION] = doc[:collation] if doc[:collation]
|
130
130
|
d[Operation::ARRAY_FILTERS] = doc[:array_filters] if doc[:array_filters]
|
data/lib/mongo/client.rb
CHANGED
@@ -62,6 +62,7 @@ module Mongo
|
|
62
62
|
:id_generator,
|
63
63
|
:local_threshold,
|
64
64
|
:logger,
|
65
|
+
:log_prefix,
|
65
66
|
:max_idle_time,
|
66
67
|
:max_pool_size,
|
67
68
|
:max_read_retries,
|
@@ -75,6 +76,7 @@ module Mongo
|
|
75
76
|
:read_concern,
|
76
77
|
:read_retry_interval,
|
77
78
|
:replica_set,
|
79
|
+
:resolv_options,
|
78
80
|
:retry_reads,
|
79
81
|
:retry_writes,
|
80
82
|
:scan,
|
@@ -215,13 +217,16 @@ module Mongo
|
|
215
217
|
# @option options [ Float ] :connect_timeout The timeout, in seconds, to
|
216
218
|
# attempt a connection.
|
217
219
|
# @option options [ String ] :database The database to connect to.
|
218
|
-
# @option options [ Float ] :heartbeat_frequency The
|
219
|
-
# the server monitor to refresh
|
220
|
+
# @option options [ Float ] :heartbeat_frequency The interval, in seconds,
|
221
|
+
# for the server monitor to refresh its description via ismaster.
|
220
222
|
# @option options [ Object ] :id_generator A custom object to generate ids
|
221
223
|
# for documents. Must respond to #generate.
|
222
224
|
# @option options [ Integer ] :local_threshold The local threshold boundary
|
223
225
|
# in seconds for selecting a near server for an operation.
|
224
|
-
# @option options [ Logger ] :logger A custom logger
|
226
|
+
# @option options [ Logger ] :logger A custom logger to use.
|
227
|
+
# @option options [ String ] :log_prefix A custom log prefix to use when
|
228
|
+
# logging. This option is experimental and subject to change in a future
|
229
|
+
# version of the driver.
|
225
230
|
# @option options [ Integer ] :max_idle_time The maximum seconds a socket can remain idle
|
226
231
|
# since it has been checked in to the pool.
|
227
232
|
# @option options [ Integer ] :max_pool_size The maximum size of the
|
@@ -361,6 +366,8 @@ module Mongo
|
|
361
366
|
# Can be :w => Integer|String, :fsync => Boolean, :j => Boolean.
|
362
367
|
# @option options [ Integer ] :zlib_compression_level The Zlib compression level to use, if using compression.
|
363
368
|
# See Ruby's Zlib module for valid levels.
|
369
|
+
# @option options [ Hash ] :resolv_options For internal driver use only.
|
370
|
+
# Options to pass through to Resolv::DNS constructor for SRV lookups.
|
364
371
|
#
|
365
372
|
# @since 2.0.0
|
366
373
|
def initialize(addresses_or_uri, options = nil)
|
@@ -370,8 +377,14 @@ module Mongo
|
|
370
377
|
options = {}
|
371
378
|
end
|
372
379
|
|
380
|
+
srv_uri = nil
|
373
381
|
if addresses_or_uri.is_a?(::String)
|
374
382
|
uri = URI.get(addresses_or_uri, options)
|
383
|
+
if uri.is_a?(URI::SRVProtocol)
|
384
|
+
# If the URI is an SRV URI, note this so that we can start
|
385
|
+
# SRV polling if the topology is a sharded cluster.
|
386
|
+
srv_uri = uri
|
387
|
+
end
|
375
388
|
addresses = uri.servers
|
376
389
|
uri_options = uri.client_options.dup
|
377
390
|
# Special handing for :write and :write_concern: allow client Ruby
|
@@ -382,8 +395,10 @@ module Mongo
|
|
382
395
|
uri_options.delete(:write_concern)
|
383
396
|
end
|
384
397
|
options = uri_options.merge(options)
|
398
|
+
@srv_records = uri.srv_records
|
385
399
|
else
|
386
400
|
addresses = addresses_or_uri
|
401
|
+
@srv_records = nil
|
387
402
|
end
|
388
403
|
|
389
404
|
unless options[:retry_reads] == false
|
@@ -407,6 +422,7 @@ module Mongo
|
|
407
422
|
=end
|
408
423
|
@options.freeze
|
409
424
|
validate_options!
|
425
|
+
validate_authentication_options!
|
410
426
|
|
411
427
|
@database = Database.new(self, @options[:database], @options)
|
412
428
|
|
@@ -418,8 +434,7 @@ module Mongo
|
|
418
434
|
sdam_proc.call(self)
|
419
435
|
end
|
420
436
|
|
421
|
-
@
|
422
|
-
@cluster = Cluster.new(addresses, @monitoring, cluster_options)
|
437
|
+
@cluster = Cluster.new(addresses, @monitoring, cluster_options.merge(srv_uri: srv_uri))
|
423
438
|
|
424
439
|
# Unset monitoring, it will be taken out of cluster from now on
|
425
440
|
remove_instance_variable('@monitoring')
|
@@ -435,7 +450,6 @@ module Mongo
|
|
435
450
|
options.reject do |key, value|
|
436
451
|
CRUD_OPTIONS.include?(key.to_sym)
|
437
452
|
end.merge(
|
438
|
-
server_selection_semaphore: @server_selection_semaphore,
|
439
453
|
# but need to put the database back in for auth...
|
440
454
|
database: options[:database],
|
441
455
|
|
@@ -444,7 +458,14 @@ module Mongo
|
|
444
458
|
# applications should read these values from client, not from cluster
|
445
459
|
max_read_retries: options[:max_read_retries],
|
446
460
|
read_retry_interval: options[:read_retry_interval],
|
447
|
-
)
|
461
|
+
).tap do |options|
|
462
|
+
# If the client has a cluster already, forward srv_uri to the new
|
463
|
+
# cluster to maintain SRV monitoring. If the client is brand new,
|
464
|
+
# its constructor sets srv_uri manually.
|
465
|
+
if cluster
|
466
|
+
options.update(srv_uri: cluster.options[:srv_uri])
|
467
|
+
end
|
468
|
+
end
|
448
469
|
end
|
449
470
|
|
450
471
|
# Get the maximum number of times the client can retry a read operation
|
@@ -616,6 +637,7 @@ module Mongo
|
|
616
637
|
options.update(opts)
|
617
638
|
@options = options.freeze
|
618
639
|
validate_options!
|
640
|
+
validate_authentication_options!
|
619
641
|
end
|
620
642
|
end
|
621
643
|
|
@@ -647,17 +669,11 @@ module Mongo
|
|
647
669
|
|
648
670
|
# Close all connections.
|
649
671
|
#
|
650
|
-
# @example Disconnect the client.
|
651
|
-
# client.close
|
652
|
-
#
|
653
|
-
# @param [ Boolean ] wait Whether to wait for background threads to
|
654
|
-
# finish running.
|
655
|
-
#
|
656
672
|
# @return [ true ] Always true.
|
657
673
|
#
|
658
674
|
# @since 2.1.0
|
659
|
-
def close
|
660
|
-
@cluster.disconnect!
|
675
|
+
def close
|
676
|
+
@cluster.disconnect!
|
661
677
|
true
|
662
678
|
end
|
663
679
|
|
@@ -857,7 +873,7 @@ module Mongo
|
|
857
873
|
end
|
858
874
|
|
859
875
|
# Validates all options after they are set on the client.
|
860
|
-
# This method is intended to catch combinations of options which
|
876
|
+
# This method is intended to catch combinations of options which are
|
861
877
|
# not allowed.
|
862
878
|
def validate_options!
|
863
879
|
if options[:write] && options[:write_concern] && options[:write] != options[:write_concern]
|
@@ -865,6 +881,48 @@ module Mongo
|
|
865
881
|
end
|
866
882
|
end
|
867
883
|
|
884
|
+
# Validates all authentication-related options after they are set on the client
|
885
|
+
# This method is intended to catch combinations of options which are not allowed
|
886
|
+
def validate_authentication_options!
|
887
|
+
auth_mech = options[:auth_mech]
|
888
|
+
user = options[:user]
|
889
|
+
password = options[:password]
|
890
|
+
auth_source = options[:auth_source]
|
891
|
+
mech_properties = options[:auth_mech_properties]
|
892
|
+
|
893
|
+
if auth_mech.nil?
|
894
|
+
if user && user.empty?
|
895
|
+
raise Mongo::Auth::InvalidConfiguration.new('empty username is not supported for default auth mechanism')
|
896
|
+
end
|
897
|
+
|
898
|
+
return
|
899
|
+
end
|
900
|
+
|
901
|
+
if !Mongo::Auth::SOURCES.key?(auth_mech)
|
902
|
+
raise Mongo::Auth::InvalidMechanism.new(auth_mech)
|
903
|
+
end
|
904
|
+
|
905
|
+
if user.nil? && auth_mech != :mongodb_x509
|
906
|
+
raise Mongo::Auth::InvalidConfiguration.new("user is required for mechanism #{auth_mech}")
|
907
|
+
end
|
908
|
+
|
909
|
+
if password.nil? && ![:gssapi, :mongodb_x509].include?(auth_mech)
|
910
|
+
raise Mongo::Auth::InvalidConfiguration.new("password is required for mechanism #{auth_mech}")
|
911
|
+
end
|
912
|
+
|
913
|
+
if password && auth_mech == :mongodb_x509
|
914
|
+
raise Mongo::Auth::InvalidConfiguration.new('password is not supported for mongodb_x509')
|
915
|
+
end
|
916
|
+
|
917
|
+
if ![:external, nil].include?(auth_source) && [:gssapi, :mongodb_x509].include?(auth_mech)
|
918
|
+
raise Mongo::Auth::InvalidConfiguration.new("#{auth_source} is an invalid auth source for #{auth_mech}; valid options are $external and nil")
|
919
|
+
end
|
920
|
+
|
921
|
+
if mech_properties && auth_mech != :gssapi
|
922
|
+
raise Mongo::Auth::InvalidConfiguration.new("mechanism_properties are not supported for #{auth_mech}")
|
923
|
+
end
|
924
|
+
end
|
925
|
+
|
868
926
|
def valid_compressors(compressors)
|
869
927
|
compressors.select do |compressor|
|
870
928
|
if !VALID_COMPRESSORS.include?(compressor)
|