Skip to content

DRIVERS-2501 Break NoWritesPerformed-Only Error Sequence #1349

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Dec 2, 2022

Conversation

prestonvasquez
Copy link
Member

@prestonvasquez prestonvasquez commented Nov 17, 2022

DRIVERS-2501

Please complete the following before merging:

  • Update changelog.
  • Make sure there are generated JSON files from the YAML test files.
  • Test changes in at least one language driver.
  • Test these changes against all server versions and topologies (including standalone, replica set, sharded clusters, and serverless).

@prestonvasquez prestonvasquez requested a review from a team as a code owner November 17, 2022 21:11
@prestonvasquez prestonvasquez requested review from jmikola and ShaneHarvey and removed request for a team November 17, 2022 21:11
@ShaneHarvey
Copy link
Member

@juliusgeo is going to test this in: mongodb/mongo-python-driver#1117

@@ -405,7 +405,8 @@ If a retry attempt also fails, drivers MUST update their topology according to
the SDAM spec (see: `Error Handling`_). If an error would not allow the caller
to infer that an attempt was made (e.g. connection pool exception originating
from the driver) or the error is labeled "NoWritesPerformed", the error from
the previous attempt should be raised.
the previous attempt should be raised. If all server errors are labeled
"NoWritesPerformed", then the first error should be raised.
Copy link
Member

Choose a reason for hiding this comment

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

If all server errors are labeled "NoWritesPerformed", then the first error should be raised.

Is previousError in the code below intended to be the first error encountered? If not, and previousError could be updated multiple times, the behavior below seems to conflict with this statement as the first error is never permanently saved.

Copy link
Member Author

Choose a reason for hiding this comment

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

Assuming that an error occurs, the idea is to always set "previousError" with the first error encountered, without condition. Otherwise, if the error is NOT labeled "NoWritesPerformed", then update the "previousError" to the "originalError":

if (originalError is not DriverException && ! originalError.hasErrorLabel("NoWritesPerformed") ||
        previousError == null) {
    previousError = originalError;
}

This behavior will "save" the first error only on the condition that the sequence of errors encountered are all labeled "NoWritesPerformed". Otherwise, a sequence of errors all labeled "NoWritesPerformed" will result in a "null" error.

Copy link
Contributor

@juliusgeo juliusgeo left a comment

Choose a reason for hiding this comment

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

LGTM!

@@ -494,7 +506,7 @@ The above rules are implemented in the following pseudo-code:
* is very rare, and likely means that the cluster is in the midst of a
* downgrade. */
if ( ! isRetryableWritesSupported(server)) {
throw originalError;
throw currentError;
Copy link
Member

Choose a reason for hiding this comment

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

I beleive this should be previousError too.

Copy link
Member

Choose a reason for hiding this comment

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

(adding another comment because I accidentally approved.)

Copy link
Member Author

Choose a reason for hiding this comment

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

Originally added in SPEC-972 , the comment for this block says

If the server selected for retrying is too old, throw the original error

What is the purpose for changing the logic here?

Copy link
Member

@ShaneHarvey ShaneHarvey Dec 2, 2022

Choose a reason for hiding this comment

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

Using currentError here is no longer correct when there are multiple retries. Imagine:

  • Attempt 1 fails with NoWritesPerformed
  • Attempt 2 fails with ShutdownInProgress
  • Attempt 3 fails with NoWritesPerformed
  • Attempt 4 selects a server that doesn't support retryable writes

We have to raise the previous non-NoWritesPerformed error which would be the ShutdownInProgress from attempt 2, not the one from attempt 3.

@@ -494,7 +506,7 @@ The above rules are implemented in the following pseudo-code:
* is very rare, and likely means that the cluster is in the midst of a
* downgrade. */
if ( ! isRetryableWritesSupported(server)) {
throw originalError;
throw currentError;
Copy link
Member

Choose a reason for hiding this comment

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

(adding another comment because I accidentally approved.)

Copy link
Member

@ShaneHarvey ShaneHarvey left a comment

Choose a reason for hiding this comment

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

LGTM!

@prestonvasquez prestonvasquez merged commit 2051f35 into mongodb:master Dec 2, 2022
@prestonvasquez prestonvasquez deleted the DRIVERS-2501 branch December 2, 2022 17:47
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.

4 participants