Skip to content

Commit 498c673

Browse files
committed
PYTHON-2791 Ignore erroneous serviceId field for non-LB connections (#663)
(cherry picked from commit b823b95)
1 parent 605620b commit 498c673

File tree

3 files changed

+31
-4
lines changed

3 files changed

+31
-4
lines changed

pymongo/pool.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,8 @@ def _ismaster(self, cluster_time, topology_version,
634634
if self.opts.load_balanced and _MOCK_SERVICE_ID:
635635
process_id = doc.get('topologyVersion', {}).get('processId')
636636
doc.setdefault('serviceId', process_id)
637+
if not self.opts.load_balanced:
638+
doc.pop('serviceId', None)
637639
ismaster = IsMaster(doc, awaitable=awaitable)
638640
self.is_writable = ismaster.is_writable
639641
self.max_wire_version = ismaster.max_wire_version
@@ -671,6 +673,9 @@ def _next_reply(self):
671673
unpacked_docs = reply.unpack_response()
672674
response_doc = unpacked_docs[0]
673675
helpers._check_command_response(response_doc, self.max_wire_version)
676+
# Remove after PYTHON-2712.
677+
if not self.opts.load_balanced:
678+
response_doc.pop('serviceId', None)
674679
return response_doc
675680

676681
def command(self, dbname, spec, slave_ok=False,

pymongo/topology_description.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,7 @@ def updated_topology_description(topology_description, server_description):
361361
topology_description._topology_settings)
362362

363363
if topology_type == TOPOLOGY_TYPE.Unknown:
364-
if server_type == SERVER_TYPE.Standalone:
364+
if server_type in (SERVER_TYPE.Standalone, SERVER_TYPE.LoadBalancer):
365365
if len(topology_description._topology_settings.seeds) == 1:
366366
topology_type = TOPOLOGY_TYPE.Single
367367
else:

test/test_topology.py

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@
1818

1919
sys.path[0:0] = [""]
2020

21+
from bson.objectid import ObjectId
2122
from bson.py3compat import imap
23+
2224
from pymongo import common
2325
from pymongo.read_preferences import ReadPreference, Secondary
2426
from pymongo.server_type import SERVER_TYPE
@@ -294,7 +296,7 @@ def test_readable_writable(self):
294296
'setName': 'rs',
295297
'hosts': ['a', 'b']})
296298

297-
self.assertTrue(
299+
self.assertEqual(
298300
t.description.topology_type_name, 'ReplicaSetWithPrimary')
299301
self.assertTrue(t.description.has_writable_server())
300302
self.assertTrue(t.description.has_readable_server())
@@ -319,7 +321,7 @@ def test_readable_writable(self):
319321
'setName': 'rs',
320322
'hosts': ['a', 'b']})
321323

322-
self.assertTrue(
324+
self.assertEqual(
323325
t.description.topology_type_name, 'ReplicaSetNoPrimary')
324326
self.assertFalse(t.description.has_writable_server())
325327
self.assertFalse(t.description.has_readable_server())
@@ -344,7 +346,7 @@ def test_readable_writable(self):
344346
'hosts': ['a', 'b'],
345347
'tags': {'tag': 'exists'}})
346348

347-
self.assertTrue(
349+
self.assertEqual(
348350
t.description.topology_type_name, 'ReplicaSetWithPrimary')
349351
self.assertTrue(t.description.has_writable_server())
350352
self.assertTrue(t.description.has_readable_server())
@@ -680,6 +682,26 @@ def test_topology_repr(self):
680682
"<ServerDescription ('c', 27017) server_type: Unknown,"
681683
" rtt: None>]>" % (t._topology_id,))
682684

685+
def test_unexpected_load_balancer(self):
686+
# Note: This behavior should not be reachable in practice but we
687+
# should handle it gracefully nonetheless. See PYTHON-2791.
688+
# Load balancers are included in topology with a single seed.
689+
t = create_mock_topology(seeds=['a'])
690+
mock_lb_response = {'ok': 1, 'msg': 'isdbgrid',
691+
'serviceId': ObjectId(), 'maxWireVersion': 13}
692+
got_ismaster(t, ('a', 27017), mock_lb_response)
693+
sds = t.description.server_descriptions()
694+
self.assertIn(('a', 27017), sds)
695+
self.assertEqual(sds[('a', 27017)].server_type_name, 'LoadBalancer')
696+
self.assertEqual(t.description.topology_type_name, 'Single')
697+
self.assertTrue(t.description.has_writable_server())
698+
699+
# Load balancers are removed from a topology with multiple seeds.
700+
t = create_mock_topology(seeds=['a', 'b'])
701+
got_ismaster(t, ('a', 27017), mock_lb_response)
702+
self.assertNotIn(('a', 27017), t.description.server_descriptions())
703+
self.assertEqual(t.description.topology_type_name, 'Unknown')
704+
683705

684706
def wait_for_master(topology):
685707
"""Wait for a Topology to discover a writable server.

0 commit comments

Comments
 (0)