Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/zizmor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ jobs:
with:
persist-credentials: false
- name: Run zizmor 🌈
uses: zizmorcore/zizmor-action@0f0557ab4a0b31211d42435e42df31cbd63fdd59
uses: zizmorcore/zizmor-action@1c7106082dbc1753372e3924b7da1b9417011a21
1 change: 1 addition & 0 deletions doc/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ PyMongo 4.14 brings a number of changes including:
- Added :meth:`pymongo.asynchronous.mongo_client.AsyncMongoClient.append_metadata` and
:meth:`pymongo.mongo_client.MongoClient.append_metadata` to allow instantiated MongoClients to send client metadata
on-demand
- Improved performance of selecting a server with the Primary selector.

- Introduces a minor breaking change. When encoding :class:`bson.binary.BinaryVector`, a ``ValueError`` will be raised
if the 'padding' metadata field is < 0 or > 7, or non-zero for any type other than PACKED_BIT.
Expand Down
10 changes: 9 additions & 1 deletion pymongo/topology_description.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
from bson.objectid import ObjectId
from pymongo import common
from pymongo.errors import ConfigurationError, PyMongoError
from pymongo.read_preferences import ReadPreference, _AggWritePref, _ServerMode
from pymongo.read_preferences import Primary, ReadPreference, _AggWritePref, _ServerMode
from pymongo.server_description import ServerDescription
from pymongo.server_selectors import Selection
from pymongo.server_type import SERVER_TYPE
Expand Down Expand Up @@ -324,6 +324,14 @@ def apply_selector(
description = self.server_descriptions().get(address)
return [description] if description else []

# Primary selection fast path.
if self.topology_type == TOPOLOGY_TYPE.ReplicaSetWithPrimary and type(selector) is Primary:
for sd in self._server_descriptions.values():
if sd.server_type == SERVER_TYPE.RSPrimary:
return [sd]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh one more thing, don't we have to call the custom_selector here if one was provided?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And add a test for it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll have to defer for now, working on a HELP ticket

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

# No primary found, return an empty list.
return []

selection = Selection.from_topology_description(self)
# Ignore read preference for sharded clusters.
if self.topology_type != TOPOLOGY_TYPE.Sharded:
Expand Down
4 changes: 2 additions & 2 deletions test/asynchronous/test_server_selection.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,12 +130,12 @@ async def test_selector_called(self):
test_collection = mongo_client.testdb.test_collection
self.addAsyncCleanup(mongo_client.drop_database, "testdb")

# Do N operations and test selector is called at least N times.
# Do N operations and test selector is called at least N-1 times due to fast path.
await test_collection.insert_one({"age": 20, "name": "John"})
await test_collection.insert_one({"age": 31, "name": "Jane"})
await test_collection.update_one({"name": "Jane"}, {"$set": {"age": 21}})
await test_collection.find_one({"name": "Roe"})
self.assertGreaterEqual(selector.call_count, 4)
self.assertGreaterEqual(selector.call_count, 3)

@async_client_context.require_replica_set
async def test_latency_threshold_application(self):
Expand Down
4 changes: 2 additions & 2 deletions test/test_server_selection.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,12 +130,12 @@ def test_selector_called(self):
test_collection = mongo_client.testdb.test_collection
self.addCleanup(mongo_client.drop_database, "testdb")

# Do N operations and test selector is called at least N times.
# Do N operations and test selector is called at least N-1 times due to fast path.
test_collection.insert_one({"age": 20, "name": "John"})
test_collection.insert_one({"age": 31, "name": "Jane"})
test_collection.update_one({"name": "Jane"}, {"$set": {"age": 21}})
test_collection.find_one({"name": "Roe"})
self.assertGreaterEqual(selector.call_count, 4)
self.assertGreaterEqual(selector.call_count, 3)

@client_context.require_replica_set
def test_latency_threshold_application(self):
Expand Down
Loading