lib/mongo/server_selector/selectable.rb in mongo-2.10.1 vs lib/mongo/server_selector/selectable.rb in mongo-2.10.2
- old
+ new
@@ -191,10 +191,16 @@
=end
loop do
servers = candidates(cluster)
if Lint.enabled?
servers.each do |server|
+ # It is possible for a server to have a nil average RTT here
+ # because the ARTT comes from description which may be updated
+ # by a background thread while server selection is running.
+ # Currently lint mode is not a public feature, if/when this
+ # changes (https://jira.mongodb.org/browse/RUBY-1576) the
+ # requirement for ARTT to be not nil would need to be removed.
if server.average_round_trip_time.nil?
raise Error::LintError, "Server #{server.address} has nil average rtt"
end
end
end
@@ -359,14 +365,37 @@
# @return [ Array ] The near servers.
#
# @since 2.0.0
def near_servers(candidates = [], local_threshold = nil)
return candidates if candidates.empty?
- nearest_server = candidates.min_by(&:average_round_trip_time)
+
+ # Average RTT on any server may change at any time by the server
+ # monitor's background thread. ARTT may also become nil if the
+ # server is marked unknown. Take a snapshot of ARTTs for the duration
+ # of this method.
+
+ candidates = candidates.map do |server|
+ {server: server, artt: server.average_round_trip_time}
+ end.reject do |candidate|
+ candidate[:artt].nil?
+ end
+
+ return candidates if candidates.empty?
+
+ nearest_candidate = candidates.min_by do |candidate|
+ candidate[:artt]
+ end
+
# Default for legacy signarure
local_threshold ||= self.local_threshold
- threshold = nearest_server.average_round_trip_time + local_threshold
- candidates.select { |server| server.average_round_trip_time <= threshold }.shuffle!
+
+ threshold = nearest_candidate[:artt] + local_threshold
+
+ candidates.select do |candidate|
+ candidate[:artt] <= threshold
+ end.map do |candidate|
+ candidate[:server]
+ end.shuffle!
end
# Select the servers matching the defined tag sets.
#
# @param [ Array ] candidates List of candidate servers from which those