Skip to content

Commit 8d1c233

Browse files
Brandon BlackTylerBrock
Brandon Black
authored andcommitted
RUBY-560 fixing issue with check_connection_health with auth enabled
Calls from `ShardingPoolManager#check_connection_health` to `client['config']['mongos']` were failing when auth was enabled. Access to this collection requries an authenticated admin user. In addition, the previous approach of comparing the seed list to the contents of the `mongos` collection was fundamentally flawed since MongoDB keeps every `mongos` that has ever connected to the cluster in that collection (even long gone, inactive `mongos` instances). We're now simply calling `isMaster()` on each mongos to confirm that 1) it is active and reachable and 2) it is indeed a `mongos`. If either of these conditions are not true, we set `@refresh_required` to true and call close on the member.
1 parent f12e907 commit 8d1c233

File tree

2 files changed

+18
-39
lines changed

2 files changed

+18
-39
lines changed

lib/mongo/util/sharding_pool_manager.rb

+18-14
Original file line numberDiff line numberDiff line change
@@ -27,24 +27,28 @@ def connect
2727
end
2828
end
2929

30-
# We want to refresh to the member with the fastest ping time
31-
# but also want to minimize refreshes
32-
# We're healthy if the primary is pingable. If this isn't the case,
33-
# or the members have changed, set @refresh_required to true, and return.
34-
# The config.mongos find can't be part of the connect call chain due to infinite recursion
30+
# Checks that each node is healthy (via check_is_master) and that each
31+
# node is in fact a mongos. If either criteria are not true, a refresh is
32+
# set to be triggered and close() is called on the node.
33+
#
34+
# @return [Boolean] indicating if a refresh is required.
3535
def check_connection_health
36-
return if thread_local[:locks][:connecting_manager]
37-
begin
38-
seeds = @client['config']['mongos'].find.map do |mongos|
39-
Support.normalize_seeds(mongos['_id'])
40-
end
41-
if discovered_seeds != seeds
42-
@seeds = seeds
36+
@refresh_required = false
37+
@members.each do |member|
38+
begin
39+
config = @client.check_is_master([member.host, member.port])
40+
unless config && config.has_key?('msg')
41+
@refresh_required = true
42+
member.close
43+
end
44+
rescue OperationTimeout
4345
@refresh_required = true
46+
member.close
4447
end
45-
rescue Mongo::OperationFailure
46-
@refresh_required = true
48+
break if @refresh_required
4749
end
50+
@refresh_required
4851
end
52+
4953
end
5054
end

test/unit/sharding_pool_manager_test.rb

-25
Original file line numberDiff line numberDiff line change
@@ -59,30 +59,5 @@ class ShardingPoolManagerTest < Test::Unit::TestCase
5959
assert_equal 500, manager.max_bson_size
6060
assert_equal 700 , manager.max_message_size
6161
end
62-
63-
should "maintain seed format when checking connection health" do
64-
65-
@db.stubs(:command).returns(
66-
# First call to get a socket.
67-
@ismaster.merge({'ismaster' => true}),
68-
69-
# Subsequent calls to configure pools.
70-
@ismaster.merge({'ismaster' => true}),
71-
@ismaster.merge({'secondary' => true, 'maxMessageSizeBytes' => 700}),
72-
@ismaster.merge({'secondary' => true, 'maxBsonObjectSize' => 500}),
73-
@ismaster.merge({'arbiterOnly' => true})
74-
)
75-
76-
config_db = new_mock_db
77-
mongos_coll = mock('collection')
78-
mongos_coll.stubs(:find).returns(@hosts.map{|h| {'_id' => h}})
79-
config_db.stubs(:[]).with('mongos').returns(mongos_coll)
80-
@client.stubs(:[]).with('config').returns(config_db)
81-
82-
manager = Mongo::ShardingPoolManager.new(@client, @hosts)
83-
manager.check_connection_health
84-
85-
assert manager.seeds.all? {|s| s.is_a?(Array) && s[0].is_a?(String) && s[1].is_a?(Integer)}
86-
end
8762
end
8863
end

0 commit comments

Comments
 (0)