Skip to content

PYTHON-5885 Client Backpressure with baseBackoffMS#2877

Open
NoahStapp wants to merge 27 commits into
mongodb:mainfrom
NoahStapp:backpressure-v2
Open

PYTHON-5885 Client Backpressure with baseBackoffMS#2877
NoahStapp wants to merge 27 commits into
mongodb:mainfrom
NoahStapp:backpressure-v2

Conversation

@NoahStapp

@NoahStapp NoahStapp commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

PYTHON-5885

Changes in this PR

Adds baseBackoffMS support for backoff calculation on retryable overload errors.

Test Plan

Adds a new prose test test_05_overload_errors_with_retryafterms_override_backoff to verify the baseBackoffMS behavior. Note that this new test requires a server with baseBackoffMS support.

Checklist

Checklist for Author

  • Did you update the changelog (if necessary)?
  • Is there test coverage?
  • [ ] Is any followup work tracked in a JIRA ticket? If so, add link(s).

Checklist for Reviewer

  • Does the title of the PR reference a JIRA Ticket?
  • Do you fully understand the implementation? (Would you be comfortable explaining how this code works to someone else?)
  • Is all relevant documentation (README or docstring) updated?

@codecov-commenter

codecov-commenter commented Jun 16, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@NoahStapp
NoahStapp marked this pull request as ready for review July 1, 2026 15:50
@NoahStapp
NoahStapp requested a review from a team as a code owner July 1, 2026 15:50
@NoahStapp
NoahStapp requested review from aclark4life and Copilot July 1, 2026 15:50
@NoahStapp

Copy link
Copy Markdown
Contributor Author

Note: SERVER-130142 will rename retryAfterMS to baseBackoffMS. That change will require the spec to update as well as this PR.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds support for using retryAfterMS from retryable overload errors to influence the client’s adaptive retry backoff, plus updates handshake backpressure metadata and related tests/docs.

Changes:

  • Parse and propagate retryAfterMS from server error documents into the overload backoff calculation.
  • Update hello/handshake backpressure field value (and metadata tests) to "2".
  • Add a new prose-style timing test validating that retryAfterMS reduces overload backoff.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
pymongo/errors.py Parses retryAfterMS from error details into PyMongoError.
pymongo/synchronous/mongo_client.py Uses retryAfterMS override when computing overload retry backoff (sync).
pymongo/asynchronous/mongo_client.py Uses retryAfterMS override when computing overload retry backoff (async).
pymongo/synchronous/helpers.py Adjusts backoff helper to accept an override base backoff (sync).
pymongo/asynchronous/helpers.py Adjusts backoff helper to accept an override base backoff (async).
pymongo/synchronous/pool.py Updates handshake hello backpressure value (sync).
pymongo/asynchronous/pool.py Updates handshake hello backpressure value (async).
test/test_client_backpressure.py Adds a new test for retryAfterMS-driven backoff behavior (sync).
test/asynchronous/test_client_backpressure.py Adds a new test for retryAfterMS-driven backoff behavior (async).
test/test_client_metadata.py Updates handshake backpressure assertion (sync).
test/asynchronous/test_client_metadata.py Updates handshake backpressure assertion (async).
doc/changelog.rst Updates changelog entry for 4.18.0.

Comment thread pymongo/errors.py Outdated
Comment thread pymongo/errors.py Outdated
Comment thread pymongo/synchronous/mongo_client.py Outdated
Comment thread pymongo/asynchronous/mongo_client.py Outdated
Comment thread test/test_client_metadata.py
Comment thread test/test_client_backpressure.py Outdated
Comment thread test/asynchronous/test_client_backpressure.py Outdated
Comment thread doc/changelog.rst Outdated
Comment thread pymongo/synchronous/mongo_client.py Outdated
Comment thread pymongo/asynchronous/mongo_client.py Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.

Comment thread doc/changelog.rst Outdated
Comment thread test/test_client_backpressure.py Outdated
Comment thread test/asynchronous/test_client_backpressure.py Outdated
@NoahStapp NoahStapp changed the title PYTHON-5885 - Client Backpressure with retryAfterMS PYTHON-5885 - Client Backpressure with baseBackoffMS Jul 8, 2026
@Jibola Jibola changed the title PYTHON-5885 - Client Backpressure with baseBackoffMS PYTHON-5885 Client Backpressure with baseBackoffMS Jul 9, 2026
Comment thread pymongo/errors.py Outdated
Comment on lines +36 to +45
def __init__(
self,
message: str = "",
error_labels: Optional[Iterable[str]] = None,
base_backoff_ms: Optional[int] = None,
) -> None:
super().__init__(message)
self._message = message
self._error_labels = set(error_labels or [])
self._base_backoff_ms = base_backoff_ms

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why does the base PyMongoError also need to initialize self._base_backoff_ms? It's only a viable label on OperationFailure.

@aclark4life

Copy link
Copy Markdown
Contributor

retryAfterMS is now baseBackoffMScorrect? Is so can you update the PR desc ?

Comment thread pymongo/asynchronous/mongo_client.py Outdated
if overloaded:
self._max_retries = self._client.options.max_adaptive_retries
always_retryable = exc.has_error_label("RetryableError") and overloaded
self._base_backoff_ms = exc_to_check._base_backoff_ms

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🤖 suggests:

self._base_backoff_ms = getattr(exc_to_check, "_base_backoff_ms", None)

here and here because _base_backoff_ms is a property defined only on OperationFailure but exc_to_check can be a ConnectionFailure and the if overloaded: guard only checks the error label not the type.

@NoahStapp NoahStapp Jul 20, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The server can only attach SystemOverloadedError to OperationFailure errors, so this can't ever occur currently. We could add the getattr as a safeguard in case that changes in the future, but it also makes that existing contract with the server less clear.

Actually, never mind. Having to add a type override here instead of getattr is silly.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated 5 comments.

Comment thread test/asynchronous/test_client_backpressure.py Outdated
Comment thread test/asynchronous/test_client_backpressure.py
Comment thread test/test_client_backpressure.py Outdated
Comment thread test/test_client_backpressure.py
Comment thread doc/changelog.rst

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (3)

doc/changelog.rst:5

  • The changelog header uses a placeholder release date "2026/XX/XX". This is not a valid date and makes the changelog look released/dated when it isn’t; consider keeping the undated header until the release date is known.
Changes in Version 4.18.0 (2026/XX/XX)
--------------------------------------

doc/changelog.rst:13

  • This changelog bullet is a single very long line; wrap it to match the surrounding formatting and avoid exceeding typical reStructuredText line-length conventions.
- Improved performance for MongoDB 9.0's Intelligent Workload Management (IWM) by only retrying overload errors when doing so is expected to not worsen server conditions.

test/asynchronous/test_client_backpressure.py:306

  • The PR description says it adds prose test test_05_overload_errors_with_retryafterms_override_backoff, but the added test here is test_05_overload_errors_with_basebackoffms_override_backoff. Please update the PR description (or rename the test) so they match.
    @async_client_context.require_version_min(9, 0, 0, -1)
    @async_client_context.require_failCommand_appName
    async def test_05_overload_errors_with_basebackoffms_override_backoff(self, random_func):
        # Drivers should test that overload errors with `baseBackoffMS` override the default backoff duration.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants