mongo 2.4.0.rc1 → 2.4.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
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/lib/mongo/auth/cr/conversation.rb +1 -1
- data/lib/mongo/auth/ldap/conversation.rb +1 -1
- data/lib/mongo/auth/scram/conversation.rb +1 -1
- data/lib/mongo/auth/x509/conversation.rb +4 -2
- data/lib/mongo/client.rb +7 -4
- data/lib/mongo/cluster.rb +55 -5
- data/lib/mongo/cluster/app_metadata.rb +7 -1
- data/lib/mongo/cluster/topology.rb +7 -6
- data/lib/mongo/cluster/topology/replica_set.rb +48 -2
- data/lib/mongo/cluster/topology/sharded.rb +47 -1
- data/lib/mongo/cluster/topology/single.rb +55 -4
- data/lib/mongo/cluster/topology/unknown.rb +65 -9
- data/lib/mongo/error/invalid_server_preference.rb +3 -1
- data/lib/mongo/event.rb +8 -0
- data/lib/mongo/event/description_changed.rb +20 -2
- data/lib/mongo/event/member_discovered.rb +65 -0
- data/lib/mongo/event/primary_elected.rb +3 -1
- data/lib/mongo/event/standalone_discovered.rb +1 -1
- data/lib/mongo/monitoring.rb +41 -0
- data/lib/mongo/monitoring/event.rb +6 -0
- data/lib/mongo/monitoring/event/server_closed.rb +46 -0
- data/lib/mongo/monitoring/event/server_description_changed.rb +58 -0
- data/lib/mongo/monitoring/event/server_opening.rb +46 -0
- data/lib/mongo/monitoring/event/topology_changed.rb +46 -0
- data/lib/mongo/monitoring/event/topology_closed.rb +41 -0
- data/lib/mongo/monitoring/event/topology_opening.rb +41 -0
- data/lib/mongo/monitoring/publishable.rb +12 -0
- data/lib/mongo/monitoring/sdam_log_subscriber.rb +54 -0
- data/lib/mongo/monitoring/server_closed_log_subscriber.rb +30 -0
- data/lib/mongo/monitoring/server_description_changed_log_subscriber.rb +33 -0
- data/lib/mongo/monitoring/server_opening_log_subscriber.rb +30 -0
- data/lib/mongo/monitoring/topology_changed_log_subscriber.rb +40 -0
- data/lib/mongo/monitoring/topology_opening_log_subscriber.rb +30 -0
- data/lib/mongo/server.rb +6 -0
- data/lib/mongo/server/connection.rb +1 -1
- data/lib/mongo/server/description.rb +23 -3
- data/lib/mongo/server/description/inspector.rb +4 -2
- data/lib/mongo/server/description/inspector/description_changed.rb +2 -2
- data/lib/mongo/server/description/inspector/member_discovered.rb +59 -0
- data/lib/mongo/server/description/inspector/primary_elected.rb +2 -0
- data/lib/mongo/server_selector.rb +10 -5
- data/lib/mongo/server_selector/nearest.rb +1 -1
- data/lib/mongo/server_selector/primary_preferred.rb +1 -1
- data/lib/mongo/server_selector/secondary.rb +1 -1
- data/lib/mongo/server_selector/secondary_preferred.rb +1 -1
- data/lib/mongo/server_selector/selectable.rb +24 -12
- data/lib/mongo/uri.rb +1 -1
- data/lib/mongo/version.rb +1 -1
- data/mongo.gemspec +1 -1
- data/spec/mongo/auth/cr_spec.rb +6 -1
- data/spec/mongo/auth/ldap_spec.rb +6 -1
- data/spec/mongo/auth/scram_spec.rb +6 -1
- data/spec/mongo/auth/x509/conversation_spec.rb +69 -0
- data/spec/mongo/auth/x509_spec.rb +9 -4
- data/spec/mongo/client_spec.rb +40 -2
- data/spec/mongo/cluster/topology/replica_set_spec.rb +218 -9
- data/spec/mongo/cluster/topology/sharded_spec.rb +17 -2
- data/spec/mongo/cluster/topology/single_spec.rb +19 -4
- data/spec/mongo/cluster/topology/unknown_spec.rb +19 -1
- data/spec/mongo/cluster/topology_spec.rb +11 -7
- data/spec/mongo/cluster_spec.rb +25 -7
- data/spec/mongo/max_staleness_spec.rb +40 -22
- data/spec/mongo/monitoring_spec.rb +2 -2
- data/spec/mongo/sdam_monitoring_spec.rb +60 -0
- data/spec/mongo/sdam_spec.rb +77 -0
- data/spec/mongo/server/connection_pool_spec.rb +6 -1
- data/spec/mongo/server/connection_spec.rb +6 -1
- data/spec/mongo/server/description_spec.rb +90 -1
- data/spec/mongo/server_selection_spec.rb +7 -6
- data/spec/mongo/server_selector/nearest_spec.rb +7 -7
- data/spec/mongo/server_selector/primary_preferred_spec.rb +7 -7
- data/spec/mongo/server_selector/primary_spec.rb +4 -4
- data/spec/mongo/server_selector/secondary_preferred_spec.rb +6 -6
- data/spec/mongo/server_selector/secondary_spec.rb +6 -6
- data/spec/mongo/server_selector_spec.rb +8 -0
- data/spec/mongo/server_spec.rb +6 -1
- data/spec/mongo/uri_spec.rb +4 -4
- data/spec/spec_helper.rb +2 -0
- data/spec/support/max_staleness/ReplicaSetNoPrimary/Incompatible.yml +4 -4
- data/spec/support/max_staleness/ReplicaSetNoPrimary/LastUpdateTime.yml +3 -3
- data/spec/support/max_staleness/ReplicaSetNoPrimary/Nearest.yml +3 -3
- data/spec/support/max_staleness/ReplicaSetNoPrimary/Nearest2.yml +3 -3
- data/spec/support/max_staleness/ReplicaSetNoPrimary/NoKnownServers.yml +15 -0
- data/spec/support/max_staleness/ReplicaSetNoPrimary/PrimaryPreferred.yml +1 -1
- data/spec/support/max_staleness/ReplicaSetNoPrimary/PrimaryPreferred_tags.yml +3 -3
- data/spec/support/max_staleness/ReplicaSetNoPrimary/Secondary.yml +3 -3
- data/spec/support/max_staleness/ReplicaSetNoPrimary/SecondaryPreferred.yml +1 -1
- data/spec/support/max_staleness/ReplicaSetNoPrimary/SecondaryPreferred_tags.yml +3 -3
- data/spec/support/max_staleness/ReplicaSetNoPrimary/ZeroMaxStaleness.yml +23 -0
- data/spec/support/max_staleness/ReplicaSetWithPrimary/Incompatible.yml +4 -4
- data/spec/support/max_staleness/ReplicaSetWithPrimary/LastUpdateTime.yml +5 -5
- data/spec/support/max_staleness/ReplicaSetWithPrimary/{ShortHeartbeartShortMaxStaleness2.yml → LongHeartbeat.yml} +4 -4
- data/spec/support/max_staleness/ReplicaSetWithPrimary/{ShortHeartbeartShortMaxStaleness.yml → LongHeartbeat2.yml} +6 -10
- data/spec/support/max_staleness/ReplicaSetWithPrimary/MaxStalenessTooSmall.yml +3 -2
- data/spec/support/max_staleness/ReplicaSetWithPrimary/MaxStalenessWithModePrimary.yml +2 -2
- data/spec/support/max_staleness/ReplicaSetWithPrimary/Nearest.yml +3 -3
- data/spec/support/max_staleness/ReplicaSetWithPrimary/Nearest2.yml +3 -3
- data/spec/support/max_staleness/ReplicaSetWithPrimary/Nearest_tags.yml +3 -3
- data/spec/support/max_staleness/ReplicaSetWithPrimary/PrimaryPreferred.yml +2 -2
- data/spec/support/max_staleness/ReplicaSetWithPrimary/PrimaryPreferred_incompatible.yml +3 -3
- data/spec/support/max_staleness/ReplicaSetWithPrimary/SecondaryPreferred.yml +1 -1
- data/spec/support/max_staleness/ReplicaSetWithPrimary/SecondaryPreferred_tags.yml +3 -3
- data/spec/support/max_staleness/ReplicaSetWithPrimary/SecondaryPreferred_tags2.yml +3 -3
- data/spec/support/max_staleness/ReplicaSetWithPrimary/Secondary_tags.yml +3 -3
- data/spec/support/max_staleness/ReplicaSetWithPrimary/Secondary_tags2.yml +3 -3
- data/spec/support/max_staleness/ReplicaSetWithPrimary/ZeroMaxStaleness.yml +7 -11
- data/spec/support/max_staleness/Sharded/Incompatible.yml +4 -4
- data/spec/support/max_staleness/Sharded/SmallMaxStaleness.yml +10 -2
- data/spec/support/max_staleness/Single/Incompatible.yml +4 -4
- data/spec/support/max_staleness/Single/SmallMaxStaleness.yml +2 -2
- data/spec/support/max_staleness/Unknown/SmallMaxStaleness.yml +14 -0
- data/spec/support/sdam/rs/primary_mismatched_me.yml +2 -2
- data/spec/support/sdam/rs/secondary_mismatched_me.yml +2 -2
- data/spec/support/sdam_monitoring.rb +144 -0
- data/spec/support/sdam_monitoring/replica_set_with_no_primary.yml +112 -0
- data/spec/support/sdam_monitoring/replica_set_with_primary.yml +111 -0
- data/spec/support/sdam_monitoring/replica_set_with_removal.yml +106 -0
- data/spec/support/sdam_monitoring/required_replica_set.yml +84 -0
- data/spec/support/sdam_monitoring/standalone.yml +70 -0
- data/spec/support/server_discovery_and_monitoring.rb +34 -1
- data/spec/support/server_selection.rb +14 -11
- data/spec/support/shared/server_selector.rb +6 -0
- metadata +49 -13
- metadata.gz.sig +0 -0
- data/spec/mongo/server_discovery_and_monitoring_spec.rb +0 -115
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Copyright (C) 2016 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 Monitoring
|
|
17
|
+
|
|
18
|
+
# Subscribes to Topology Changed events and logs them.
|
|
19
|
+
#
|
|
20
|
+
# @since 2.4.0
|
|
21
|
+
class TopologyChangedLogSubscriber < SDAMLogSubscriber
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def log_event(event)
|
|
26
|
+
if event.previous_topology != event.new_topology
|
|
27
|
+
log_debug(
|
|
28
|
+
"Topology type '#{event.previous_topology.display_name.downcase}' changed to " +
|
|
29
|
+
"type '#{event.new_topology.display_name.downcase}'."
|
|
30
|
+
)
|
|
31
|
+
else
|
|
32
|
+
log_debug(
|
|
33
|
+
"There was a change in the members of the '#{event.new_topology.display_name.downcase}' " +
|
|
34
|
+
"topology."
|
|
35
|
+
)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Copyright (C) 2016 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 Monitoring
|
|
17
|
+
|
|
18
|
+
# Subscribes to Topology Openeing events and logs them.
|
|
19
|
+
#
|
|
20
|
+
# @since 2.4.0
|
|
21
|
+
class TopologyOpeningLogSubscriber < SDAMLogSubscriber
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def log_event(event)
|
|
26
|
+
log_debug("Topology type '#{event.topology.display_name.downcase}' initializing.")
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
data/lib/mongo/server.rb
CHANGED
|
@@ -27,6 +27,7 @@ module Mongo
|
|
|
27
27
|
# @since 2.0.0
|
|
28
28
|
class Server
|
|
29
29
|
extend Forwardable
|
|
30
|
+
include Monitoring::Publishable
|
|
30
31
|
|
|
31
32
|
# @return [ String ] The configured address for the server.
|
|
32
33
|
attr_reader :address
|
|
@@ -45,6 +46,7 @@ module Mongo
|
|
|
45
46
|
|
|
46
47
|
# Get the description from the monitor and scan on monitor.
|
|
47
48
|
def_delegators :monitor, :description, :scan!, :heartbeat_frequency, :last_scan
|
|
49
|
+
alias :heartbeat_frequency_seconds :heartbeat_frequency
|
|
48
50
|
|
|
49
51
|
# Delegate convenience methods to the monitor description.
|
|
50
52
|
def_delegators :description,
|
|
@@ -163,6 +165,10 @@ module Mongo
|
|
|
163
165
|
@cluster = cluster
|
|
164
166
|
@monitoring = monitoring
|
|
165
167
|
@options = options.freeze
|
|
168
|
+
publish_sdam_event(
|
|
169
|
+
Monitoring::SERVER_OPENING,
|
|
170
|
+
Monitoring::Event::ServerOpening.new(address, cluster.topology)
|
|
171
|
+
)
|
|
166
172
|
@monitor = Monitor.new(address, event_listeners, options.merge(app_metadata: cluster.app_metadata))
|
|
167
173
|
monitor.scan!
|
|
168
174
|
monitor.run!
|
|
@@ -175,7 +175,7 @@ module Mongo
|
|
|
175
175
|
end
|
|
176
176
|
|
|
177
177
|
def authenticate!
|
|
178
|
-
if options[:user]
|
|
178
|
+
if options[:user] || options[:auth_mech]
|
|
179
179
|
user = Auth::User.new(Options::Redacted.new(:auth_mech => default_mechanism).merge(options))
|
|
180
180
|
@server.handle_auth_failure! do
|
|
181
181
|
Auth.get(user).login(self)
|
|
@@ -239,7 +239,7 @@ module Mongo
|
|
|
239
239
|
#
|
|
240
240
|
# @param [ Address ] address The server address.
|
|
241
241
|
# @param [ Hash ] config The result of the ismaster command.
|
|
242
|
-
# @param [ Float ] average_round_trip_time The moving average time (
|
|
242
|
+
# @param [ Float ] average_round_trip_time The moving average time (sec) the ismaster
|
|
243
243
|
# call took to complete.
|
|
244
244
|
#
|
|
245
245
|
# @since 2.0.0
|
|
@@ -480,6 +480,24 @@ module Mongo
|
|
|
480
480
|
!!config[SECONDARY] && !replica_set_name.nil?
|
|
481
481
|
end
|
|
482
482
|
|
|
483
|
+
# Returns the server type as a symbol.
|
|
484
|
+
#
|
|
485
|
+
# @example Get the server type.
|
|
486
|
+
# description.server_type
|
|
487
|
+
#
|
|
488
|
+
# @return [ Symbol ] The server type.
|
|
489
|
+
#
|
|
490
|
+
# @since 2.4.0
|
|
491
|
+
def server_type
|
|
492
|
+
return :arbiter if arbiter?
|
|
493
|
+
return :ghost if ghost?
|
|
494
|
+
return :sharded if mongos?
|
|
495
|
+
return :primary if primary?
|
|
496
|
+
return :secondary if secondary?
|
|
497
|
+
return :standalone if standalone?
|
|
498
|
+
:unknown
|
|
499
|
+
end
|
|
500
|
+
|
|
483
501
|
# Is this server a standalone server?
|
|
484
502
|
#
|
|
485
503
|
# @example Is the server standalone?
|
|
@@ -501,7 +519,8 @@ module Mongo
|
|
|
501
519
|
#
|
|
502
520
|
# @since 2.0.0
|
|
503
521
|
def unknown?
|
|
504
|
-
config.empty? || config[Operation::Result::OK]
|
|
522
|
+
config.empty? || (config[Operation::Result::OK] &&
|
|
523
|
+
config[Operation::Result::OK] != 1)
|
|
505
524
|
end
|
|
506
525
|
|
|
507
526
|
# A result from another server's ismaster command before this server has
|
|
@@ -592,6 +611,7 @@ module Mongo
|
|
|
592
611
|
# @since 2.0.6
|
|
593
612
|
def ==(other)
|
|
594
613
|
return false if self.class != other.class
|
|
614
|
+
return false if unknown? || other.unknown?
|
|
595
615
|
compare_config(other)
|
|
596
616
|
end
|
|
597
617
|
alias_method :eql?, :==
|
|
@@ -599,7 +619,7 @@ module Mongo
|
|
|
599
619
|
private
|
|
600
620
|
|
|
601
621
|
def compare_config(other)
|
|
602
|
-
|
|
622
|
+
config.keys.all? do |k|
|
|
603
623
|
config[k] == other.config[k] || EXCLUDE_FOR_COMPARISON.include?(k)
|
|
604
624
|
end
|
|
605
625
|
end
|
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
+
require 'mongo/server/description/inspector/member_discovered'
|
|
16
|
+
# @deprecated. Will be removed in 3.0
|
|
15
17
|
require 'mongo/server/description/inspector/primary_elected'
|
|
16
18
|
require 'mongo/server/description/inspector/description_changed'
|
|
17
19
|
require 'mongo/server/description/inspector/standalone_discovered'
|
|
@@ -34,7 +36,7 @@ module Mongo
|
|
|
34
36
|
INSPECTORS = [
|
|
35
37
|
Inspector::StandaloneDiscovered,
|
|
36
38
|
Inspector::DescriptionChanged,
|
|
37
|
-
Inspector::
|
|
39
|
+
Inspector::MemberDiscovered
|
|
38
40
|
].freeze
|
|
39
41
|
|
|
40
42
|
# @return [ Array ] inspectors The description inspectors.
|
|
@@ -61,7 +63,7 @@ module Mongo
|
|
|
61
63
|
#
|
|
62
64
|
# @param [ Description ] description The old description.
|
|
63
65
|
# @param [ Hash ] ismaster The updated ismaster.
|
|
64
|
-
# @param [ Float ] average_round_trip_time The moving average round trip time (
|
|
66
|
+
# @param [ Float ] average_round_trip_time The moving average round trip time (sec).
|
|
65
67
|
#
|
|
66
68
|
# @return [ Description ] The new description.
|
|
67
69
|
#
|
|
@@ -46,8 +46,8 @@ module Mongo
|
|
|
46
46
|
#
|
|
47
47
|
# @since 2.0.0
|
|
48
48
|
def run(description, updated)
|
|
49
|
-
unless description == updated
|
|
50
|
-
publish(Event::DESCRIPTION_CHANGED, updated)
|
|
49
|
+
unless (description.unknown? && updated.unknown?) || (description == updated)
|
|
50
|
+
publish(Event::DESCRIPTION_CHANGED, description, updated)
|
|
51
51
|
end
|
|
52
52
|
end
|
|
53
53
|
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Copyright (C) 2015 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 Server
|
|
17
|
+
class Description
|
|
18
|
+
class Inspector
|
|
19
|
+
|
|
20
|
+
# Handles inspecting the result of an ismaster command to check if this
|
|
21
|
+
# a server is a member of a known topology.
|
|
22
|
+
#
|
|
23
|
+
# @since 2.4.0
|
|
24
|
+
class MemberDiscovered
|
|
25
|
+
include Event::Publisher
|
|
26
|
+
|
|
27
|
+
# Instantiate the member discovered inspection.
|
|
28
|
+
#
|
|
29
|
+
# @example Instantiate the inspection.
|
|
30
|
+
# MemberDiscovered.new(listeners)
|
|
31
|
+
#
|
|
32
|
+
# @param [ Event::Listeners ] event_listeners The event listeners.
|
|
33
|
+
#
|
|
34
|
+
# @since 2.4.0
|
|
35
|
+
def initialize(event_listeners)
|
|
36
|
+
@event_listeners = event_listeners
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Run the member discovered inspection.
|
|
40
|
+
#
|
|
41
|
+
# @example Run the inspection.
|
|
42
|
+
# MemberDiscovered.run(description, {})
|
|
43
|
+
#
|
|
44
|
+
# @param [ Description ] description The server description.
|
|
45
|
+
# @param [ Description ] updated The updated description.
|
|
46
|
+
#
|
|
47
|
+
# @since 2.4.0
|
|
48
|
+
def run(description, updated)
|
|
49
|
+
if (!description.primary? && updated.primary?) ||
|
|
50
|
+
(!description.mongos? && updated.mongos?) ||
|
|
51
|
+
(description.unknown? && !updated.unknown?)
|
|
52
|
+
publish(Event::MEMBER_DISCOVERED, description, updated)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -38,6 +38,11 @@ module Mongo
|
|
|
38
38
|
# @since 2.0.0
|
|
39
39
|
SERVER_SELECTION_TIMEOUT = 30.freeze
|
|
40
40
|
|
|
41
|
+
# The smallest allowed max staleness value, in seconds.
|
|
42
|
+
#
|
|
43
|
+
# @since 2.4.0
|
|
44
|
+
SMALLEST_MAX_STALENESS_SECONDS = 90
|
|
45
|
+
|
|
41
46
|
# Primary read preference.
|
|
42
47
|
#
|
|
43
48
|
# @since 2.1.0
|
|
@@ -48,11 +53,11 @@ module Mongo
|
|
|
48
53
|
#
|
|
49
54
|
# @since 2.0.0
|
|
50
55
|
PREFERENCES = {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
+
nearest: Nearest,
|
|
57
|
+
primary: Primary,
|
|
58
|
+
primary_preferred: PrimaryPreferred,
|
|
59
|
+
secondary: Secondary,
|
|
60
|
+
secondary_preferred: SecondaryPreferred
|
|
56
61
|
}.freeze
|
|
57
62
|
|
|
58
63
|
# Create a server selector object.
|
|
@@ -67,7 +67,7 @@ module Mongo
|
|
|
67
67
|
def to_mongos
|
|
68
68
|
preference = { :mode => 'nearest' }
|
|
69
69
|
preference.merge!({ :tags => tag_sets }) unless tag_sets.empty?
|
|
70
|
-
preference.merge!({
|
|
70
|
+
preference.merge!({ maxStalenessSeconds: max_staleness }) if max_staleness
|
|
71
71
|
preference
|
|
72
72
|
end
|
|
73
73
|
|
|
@@ -68,7 +68,7 @@ module Mongo
|
|
|
68
68
|
def to_mongos
|
|
69
69
|
preference = { :mode => 'primaryPreferred' }
|
|
70
70
|
preference.merge!({ :tags => tag_sets }) unless tag_sets.empty?
|
|
71
|
-
preference.merge!({
|
|
71
|
+
preference.merge!({ maxStalenessSeconds: max_staleness }) if max_staleness
|
|
72
72
|
preference
|
|
73
73
|
end
|
|
74
74
|
|
|
@@ -68,7 +68,7 @@ module Mongo
|
|
|
68
68
|
def to_mongos
|
|
69
69
|
preference = { :mode => 'secondary' }
|
|
70
70
|
preference.merge!({ :tags => tag_sets }) unless tag_sets.empty?
|
|
71
|
-
preference.merge!({
|
|
71
|
+
preference.merge!({ maxStalenessSeconds: max_staleness }) if max_staleness
|
|
72
72
|
preference
|
|
73
73
|
end
|
|
74
74
|
|
|
@@ -71,7 +71,7 @@ module Mongo
|
|
|
71
71
|
return nil if tag_sets.empty? && max_staleness.nil?
|
|
72
72
|
preference = { mode: 'secondaryPreferred' }
|
|
73
73
|
preference.merge!({ tags: tag_sets }) unless tag_sets.empty?
|
|
74
|
-
preference.merge!({
|
|
74
|
+
preference.merge!({ maxStalenessSeconds: max_staleness }) if max_staleness
|
|
75
75
|
preference
|
|
76
76
|
end
|
|
77
77
|
|
|
@@ -26,7 +26,7 @@ module Mongo
|
|
|
26
26
|
# @return [ Array ] tag_sets The tag sets used to select servers.
|
|
27
27
|
attr_reader :tag_sets
|
|
28
28
|
|
|
29
|
-
# @return [
|
|
29
|
+
# @return [ Integer ] max_staleness The maximum replication lag, in seconds, that a
|
|
30
30
|
# secondary can suffer and still be eligible for a read.
|
|
31
31
|
#
|
|
32
32
|
# @since 2.4.0
|
|
@@ -68,7 +68,7 @@ module Mongo
|
|
|
68
68
|
def initialize(options = {})
|
|
69
69
|
@options = (options || {}).freeze
|
|
70
70
|
@tag_sets = (options[:tag_sets] || []).freeze
|
|
71
|
-
@max_staleness = options[:max_staleness]
|
|
71
|
+
@max_staleness = options[:max_staleness] unless options[:max_staleness] == -1
|
|
72
72
|
validate!
|
|
73
73
|
end
|
|
74
74
|
|
|
@@ -146,19 +146,29 @@ module Mongo
|
|
|
146
146
|
@local_threshold ||= (options[:local_threshold] || ServerSelector::LOCAL_THRESHOLD)
|
|
147
147
|
end
|
|
148
148
|
|
|
149
|
-
|
|
150
|
-
|
|
149
|
+
# Get the potential candidates to select from the cluster.
|
|
150
|
+
#
|
|
151
|
+
# @example Get the server candidates.
|
|
152
|
+
# selectable.candidates(cluster)
|
|
153
|
+
#
|
|
154
|
+
# @param [ Cluster ] cluster The cluster.
|
|
155
|
+
#
|
|
156
|
+
# @return [ Array<Server> ] The candidate servers.
|
|
157
|
+
#
|
|
158
|
+
# @since 2.4.0
|
|
151
159
|
def candidates(cluster)
|
|
152
160
|
if cluster.single?
|
|
153
161
|
cluster.servers.each { |server| validate_max_staleness_support!(server) }
|
|
154
162
|
elsif cluster.sharded?
|
|
155
163
|
near_servers(cluster.servers).each { |server| validate_max_staleness_support!(server) }
|
|
156
164
|
else
|
|
157
|
-
validate_max_staleness_value!(cluster)
|
|
165
|
+
validate_max_staleness_value!(cluster) unless cluster.unknown?
|
|
158
166
|
select(cluster.servers)
|
|
159
167
|
end
|
|
160
168
|
end
|
|
161
169
|
|
|
170
|
+
private
|
|
171
|
+
|
|
162
172
|
# Select the primary from a list of provided candidates.
|
|
163
173
|
#
|
|
164
174
|
# @param [ Array ] candidates List of candidate servers to select the
|
|
@@ -200,7 +210,7 @@ module Mongo
|
|
|
200
210
|
def near_servers(candidates = [])
|
|
201
211
|
return candidates if candidates.empty?
|
|
202
212
|
nearest_server = candidates.min_by(&:average_round_trip_time)
|
|
203
|
-
threshold = nearest_server.average_round_trip_time +
|
|
213
|
+
threshold = nearest_server.average_round_trip_time + local_threshold
|
|
204
214
|
candidates.select { |server| server.average_round_trip_time <= threshold }.shuffle!
|
|
205
215
|
end
|
|
206
216
|
|
|
@@ -230,14 +240,14 @@ module Mongo
|
|
|
230
240
|
validate_max_staleness_support!(server)
|
|
231
241
|
staleness = (server.last_scan - server.last_write_date) -
|
|
232
242
|
(primary.last_scan - primary.last_write_date) +
|
|
233
|
-
(server.
|
|
243
|
+
(server.heartbeat_frequency_seconds * 1000)
|
|
234
244
|
staleness <= max_staleness_ms
|
|
235
245
|
end
|
|
236
246
|
else
|
|
237
247
|
max_write_date = candidates.collect(&:last_write_date).max
|
|
238
248
|
candidates.select do |server|
|
|
239
249
|
validate_max_staleness_support!(server)
|
|
240
|
-
staleness = max_write_date - server.last_write_date + (server.
|
|
250
|
+
staleness = max_write_date - server.last_write_date + (server.heartbeat_frequency_seconds * 1000)
|
|
241
251
|
staleness <= max_staleness_ms
|
|
242
252
|
end
|
|
243
253
|
end
|
|
@@ -258,10 +268,12 @@ module Mongo
|
|
|
258
268
|
end
|
|
259
269
|
|
|
260
270
|
def validate_max_staleness_value!(cluster)
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
271
|
+
if @max_staleness
|
|
272
|
+
heartbeat_frequency_seconds = cluster.options[:heartbeat_frequency] || Server::Monitor::HEARTBEAT_FREQUENCY
|
|
273
|
+
unless @max_staleness >= [ SMALLEST_MAX_STALENESS_SECONDS,
|
|
274
|
+
(heartbeat_frequency_seconds + Cluster::IDLE_WRITE_PERIOD_SECONDS) ].max
|
|
275
|
+
raise Error::InvalidServerPreference.new(Error::InvalidServerPreference::INVALID_MAX_STALENESS)
|
|
276
|
+
end
|
|
265
277
|
end
|
|
266
278
|
end
|
|
267
279
|
end
|
data/lib/mongo/uri.rb
CHANGED
|
@@ -374,7 +374,7 @@ module Mongo
|
|
|
374
374
|
# Read Options
|
|
375
375
|
uri_option 'readpreference', :mode, :group => :read, :type => :read_mode
|
|
376
376
|
uri_option 'readpreferencetags', :tag_sets, :group => :read, :type => :read_tags
|
|
377
|
-
uri_option '
|
|
377
|
+
uri_option 'maxstalenessseconds', :max_staleness, :group => :read
|
|
378
378
|
|
|
379
379
|
# Pool options
|
|
380
380
|
uri_option 'minpoolsize', :min_pool_size
|