PYTHON-926 - ReadPreference.NEAREST shouldn't pick arbiters.

This commit is contained in:
Bernie Hackett 2015-05-07 14:50:38 -07:00
parent c31d4808bf
commit f282babff0
3 changed files with 32 additions and 6 deletions

View File

@ -21,6 +21,10 @@ def any_server_selector(server_descriptions):
return server_descriptions
def readable_server_selector(server_descriptions):
return [s for s in server_descriptions if s.is_readable]
def writable_server_selector(server_descriptions):
return [s for s in server_descriptions if s.is_writable]
@ -49,6 +53,11 @@ def single_tag_set_server_selector(tag_set, server_descriptions):
A server tagged {'a': '1', 'b': '2'} matches the tag set {'a': '1'}.
The empty tag set {} matches any server.
The `server_descriptions` passed to this function should have
non-readable servers (e.g. RSGhost, RSArbiter, Unknown) filtered
out (e.g. by readable_server_selector or secondary_server_selector)
first.
"""
def tags_match(server_tags):
for key, value in tag_set.items():
@ -68,6 +77,11 @@ def tag_sets_server_selector(tag_sets, server_descriptions):
[{'a': 'value'}, {}] expresses a preference for servers tagged
{'a': 'value'}, but accepts any server if none matches the first
preference.
The `server_descriptions` passed to this function should have
non-readable servers (e.g. RSGhost, RSArbiter, Unknown) filtered
out (e.g. by readable_server_selector or secondary_server_selector)
first.
"""
for tag_set in tag_sets:
selected = single_tag_set_server_selector(tag_set, server_descriptions)
@ -81,6 +95,11 @@ def apply_local_threshold(latency_ms, server_descriptions):
"""All servers with round trip times within latency_ms of the fastest one.
No ServerDescription's round_trip_time can be None.
The `server_descriptions` passed to this function should have
non-readable servers (e.g. RSGhost, RSArbiter, Unknown) filtered
out (e.g. by readable_server_selector or secondary_server_selector)
first.
"""
if not server_descriptions:
# Avoid ValueError from min() with empty sequence.
@ -104,4 +123,5 @@ def secondary_with_tags_server_selector(tag_sets, server_descriptions):
def member_with_tags_server_selector(tag_sets, server_descriptions):
"""All near-enough members matching the tag sets."""
return tag_sets_server_selector(tag_sets, server_descriptions)
return tag_sets_server_selector(
tag_sets, readable_server_selector(server_descriptions))

View File

@ -127,8 +127,13 @@ class ClientContext(object):
self.rs_client = pymongo.MongoClient(
pair, replicaSet=self.replica_set_name)
self.nodes = set([partition_node(node)
for node in self.ismaster.get('hosts', [])])
nodes = [partition_node(node)
for node in self.ismaster.get('hosts', [])]
nodes.extend([partition_node(node)
for node in self.ismaster.get('passives', [])])
nodes.extend([partition_node(node)
for node in self.ismaster.get('arbiters', [])])
self.nodes = set(nodes)
self.rs_or_standalone_client = self.rs_client or self.client

View File

@ -31,7 +31,7 @@ from pymongo.read_preferences import (ReadPreference, MovingAverage,
Primary, PrimaryPreferred,
Secondary, SecondaryPreferred,
Nearest, _ServerMode)
from pymongo.server_selectors import any_server_selector
from pymongo.server_selectors import readable_server_selector
from pymongo.server_type import SERVER_TYPE
from pymongo.write_concern import WriteConcern
@ -97,7 +97,7 @@ class TestReadPreferencesBase(TestReplicaSetClientBase):
def assertReadsFrom(self, expected, **kwargs):
c = rs_client(**kwargs)
wait_until(
lambda: len(c.nodes) == self.w,
lambda: len(c.nodes - c.arbiters) == self.w,
"discovered all nodes")
used = self.read_from_which_kind(c)
@ -249,7 +249,8 @@ class TestReadPreferences(TestReadPreferencesBase):
latencies = ', '.join(
'%s: %dms' % (server.description.address,
server.description.round_trip_time)
for server in c._get_topology().select_servers(any_server_selector))
for server in c._get_topology().select_servers(
readable_server_selector))
self.assertFalse(
not_used,