Skip to content

Fix MixedBulkWriteOperation such that it does not leak MongoWriteConcernWithResponseException to users #1051

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 3 commits into from
Nov 22, 2022

Conversation

stIncMale
Copy link
Member

@stIncMale stIncMale self-assigned this Nov 18, 2022
Comment on lines 252 to 259
assertThrows(MongoWriteConcernException.class, () -> {
try {
collection.insertOne(new Document());
} catch (MongoWriteConcernException e) {
assertEquals(91, e.getCode());
throw e;
}
});
Copy link
Member Author

Choose a reason for hiding this comment

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

Now that the leak is fixed, we can expect MongoWriteConcernException here.

Copy link
Member

Choose a reason for hiding this comment

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

FYI this can also be written as:

MongoWriteConcernException e = assertThrows(MongoWriteConcernException.class, () ->  collection.insertOne(new Document()));
assertEquals(91, e.getCode());

Copy link
Member Author

Choose a reason for hiding this comment

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

Thank you, I have not realized assertThrows returns the thrown exception :) Done.

@@ -292,9 +271,10 @@ private BulkWriteResult executeBulkWriteBatch(final RetryState retryState, final
currentBulkWriteTracker = BulkWriteTracker.attachNext(retryState, currentBatch);
currentBatch = currentBulkWriteTracker.batch().orElseThrow(Assertions::fail);
} catch (MongoException exception) {
if (!(retryState.isFirstAttempt() || (exception instanceof MongoWriteConcernWithResponseException))) {
if (!retryState.isFirstAttempt() && !(exception instanceof MongoWriteConcernWithResponseException)) {
Copy link
Member Author

Choose a reason for hiding this comment

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

Changed this because I found the new form easier to understand (I was trying to understand what's going on, not very successfully, though).

Copy link
Member

Choose a reason for hiding this comment

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

Should there be a separate catch for MongoWriteConcernWithResponseException to make this easier to understand?

Copy link
Member Author

Choose a reason for hiding this comment

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

Currently we have

} catch (MongoException exception) {
    if (!retryState.isFirstAttempt() && !(exception instanceof MongoWriteConcernWithResponseException)) {
        addRetryableWriteErrorLabel(exception, maxWireVersion);
    }
    handleMongoWriteConcernWithResponseException(retryState, false);
    throw exception;
}

with the change you propose we will have

} catch (MongoWriteConcernWithResponseException exception) {
    handleMongoWriteConcernWithResponseException(retryState, false);
    throw exception;
} catch (MongoException exception) {
    if (!retryState.isFirstAttempt()) {
        addRetryableWriteErrorLabel(exception, maxWireVersion);
    }
    handleMongoWriteConcernWithResponseException(retryState, false);
    throw exception;
}

The current code is shorter and does not have code duplication, the proposed code does not have the instanceof check. To me the current approach seems the lesser of two evils.

Copy link
Member

@rozza rozza left a comment

Choose a reason for hiding this comment

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

Looks good - added a couple of comments for consideration only

Comment on lines 252 to 259
assertThrows(MongoWriteConcernException.class, () -> {
try {
collection.insertOne(new Document());
} catch (MongoWriteConcernException e) {
assertEquals(91, e.getCode());
throw e;
}
});
Copy link
Member

Choose a reason for hiding this comment

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

FYI this can also be written as:

MongoWriteConcernException e = assertThrows(MongoWriteConcernException.class, () ->  collection.insertOne(new Document()));
assertEquals(91, e.getCode());

@@ -292,9 +271,10 @@ private BulkWriteResult executeBulkWriteBatch(final RetryState retryState, final
currentBulkWriteTracker = BulkWriteTracker.attachNext(retryState, currentBatch);
currentBatch = currentBulkWriteTracker.batch().orElseThrow(Assertions::fail);
} catch (MongoException exception) {
if (!(retryState.isFirstAttempt() || (exception instanceof MongoWriteConcernWithResponseException))) {
if (!retryState.isFirstAttempt() && !(exception instanceof MongoWriteConcernWithResponseException)) {
Copy link
Member

Choose a reason for hiding this comment

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

Should there be a separate catch for MongoWriteConcernWithResponseException to make this easier to understand?

MongoCollection<Document> collection = client.getDatabase(getDefaultDatabaseName())
.getCollection("originalErrorMustBePropagatedIfNoWritesPerformed");
collection.drop();
assertThrows(MongoWriteConcernException.class, () -> {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
assertThrows(MongoWriteConcernException.class, () -> {
assertThrows(MongoWriteConcernException.class, () -> collection.insertOne(new Document()));

If it's asserting that it throws MongoWriteConcernException it can't also throw MongoWriteConcernWithResponseException

Copy link
Member Author

Choose a reason for hiding this comment

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

assertThrows(MongoWriteConcernException.class, ...) verifies that MongoWriteConcernException is thrown. What if a different exception is thrown? - it simply reports that. I want to have the The internal exception leaked message when the different exception is MongoWriteConcernWithResponseException, and I don't see another way of achieving this. Of course, if this happens, both assertions will fail with the inner assertion being the cause of the outer one.

Copy link
Collaborator

Choose a reason for hiding this comment

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

It seems overly complicated structure just to get a more helpful failure message, but I can live with it.

@stIncMale stIncMale requested a review from jyemin November 22, 2022 03:03
@stIncMale stIncMale merged commit 3387038 into mongodb:master Nov 22, 2022
@stIncMale stIncMale deleted the JAVA-4775 branch November 22, 2022 15:05
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.

3 participants