PYTHON-4008 Support exhaust cursors on mongos 7.1+ - #2985
Open
carsontung666 wants to merge 1 commit into
Open
Conversation
Member
|
Thanks @carsontung666! I will review the PR tomorrow or Monday and get back to you 😄. |
blink1073
reviewed
Aug 14, 2026
blink1073
reviewed
Aug 14, 2026
blink1073
reviewed
Aug 14, 2026
blink1073
reviewed
Aug 14, 2026
blink1073
reviewed
Aug 14, 2026
Gate the refusal on wire version instead of on server type. mongos has served exhaust getMore since 7.1 (SERVER-57297); the categorical check dates to 2.6 (4d42258, 2013), when exhaust was an OP_QUERY flag. The check is made against the connection in use, in _Query.use_command and _GetMore.use_command, since a sharded topology can hold mongoses of different versions.
carsontung666
force-pushed
the
PYTHON-4008-mongos-exhaust
branch
from
August 14, 2026 13:29
3a65b63 to
213fc64
Compare
Member
|
We're getting close! One thing I released -
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PYTHON-4008
Changes in this PR
PyMongo refuses an exhaust cursor whenever the client is connected to a mongos:
That check dates to 2.6, when exhaust was an OP_QUERY flag and mongos rejected it outright. PYTHON-1636 carried it across to OP_MSG in 4.0 unchanged. mongos has served exhaust getMore since 7.1, SERVER-57297.
MONGOS_EXHAUST_WIRE_VERSION = 22inpymongo/common.py. libmongoc uses the same value._check_exhaust_supported(conn)inpymongo/message.py, called from_Query.use_commandand_GetMore.use_command. Both already gate exhaust onconn.max_wire_version, and both run before anything reaches the wire.Cursor._supports_exhaustandCursor.add_optionkeep only their limit check.The check reads the connection, not a freshly selected server. A
Shardedtopology can hold mongoses of different versions during a rolling upgrade.Load-balanced deployments are left ungated. The connection reports
SERVER_TYPE.LoadBalancerthere, so the old check never fired either, and_should_pin_cursorpins every LB cursor anyway. An older mongos costs nothing extra, and refusing would break clients that work today.Two timing changes, both in the changelog. Against a pre-7.1 mongos the
InvalidOperationnow comes on first iteration instead of fromfind(), because the check needs a connection. AsynclimitwithEXHAUSTnow raises atfind()instead of on first iteration, matching sync, because that check no longer needs I/O.find()documents the limits. The saving is on the router-to-client leg only. The connection is monopolized for the cursor's lifetime. Nothing steers selection toward a 7.1+ mongos, so mid-upgrade the same call may succeed or raise depending on routing.A pre-7.1 mongos does not hang a client that asks for exhaust.
exhaustAllowedis an optional OP_MSG flag, so it is ignored and the cursor falls back to ordinary getMores. The refusal is because it would hold a connection for no benefit.Motivation: on a workload streaming thousands of documents through mongos, 40-45% of wall time is the client blocked between getMore round trips. Exhaust makes those reads about 23% faster on a single shard, and about 19% on two shards, where the merge leg does not use exhaust.
Test Plan
test/test_message.pyfor the wire version boundary and bothuse_commandcall sites. Mutation-tested: removing the version comparison, removing theis_mongoscondition, or deleting either call site each fails the suite.require_no_mongospurely because of this restriction now run underrequire_exhaust_cursors. They pass against a two-shard cluster fronted by a 9.0.0-alpha0 mongos, where they previously skipped, and against a standalone of the same build.InvalidOperationonmainand streams the full result set through the same mongos on this branch.tools/synchro.pyreports no drift. ruff, format and mypy pass.Not run:
test_encryption.py, for lack of an encryption environment, and the Evergreen matrix. That includes theload_balancersuite, which these gate changes newly activate. The value 22 is not pinned by a test. Doing that needs a pre-7.1 mongos.Checklist
Checklist for Author
Checklist for Reviewer
AI assistance disclosure
I used Claude Opus 5 to help write and review this change. I reviewed and understand every changed line and can explain and maintain the contribution.