Skip to content

CDRIVER-4425 Provide access to raw result if server error occurs #1144

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 29 commits into from
Nov 16, 2022

Conversation

galon1
Copy link
Contributor

@galon1 galon1 commented Nov 10, 2022

Summary

These changes provide access to the raw result document from the server if an error has occurred. For read operations the cursor will already return the original result from the server, as the result is stored in cursor->error_doc. For write operations a new field in write_result_t was required (raw_error_response), which is only populated if a server error occurs. New unified tests were added according to this specification (original new tests, but the latest edit is here).

Notes

  1. The raw responses from the server for write operations are wrapped in an errorReplies field. This is to avoid test failures that parse out expected fields in the response, since write operations process write results. For example, the index for bulkwrite operations are increased by 1 when the raw server result is processed. However, since the goal of this ticket was to return the raw result from the server with no processing (in case of future changes), I left the raw response in from the server, and I left the processed result, since users are expecting the processed result.
  2. Tests did not include a name field when running createIndex, but a name field is required for createIndexes which is how the test runner executes createIndex commands. So if no name field was set, I just created a name field so the command can be executed.

@galon1 galon1 requested a review from kevinAlbs November 10, 2022 17:09
@galon1 galon1 changed the title CDRIVER-4425 CDRIVER-4425 Provide access to raw result if server error occurs Nov 10, 2022
@galon1 galon1 marked this pull request as draft November 10, 2022 18:03
@galon1 galon1 marked this pull request as ready for review November 11, 2022 14:56
@@ -85,4 +85,7 @@ _mongoc_error_is_state_change (bson_error_t *error);
bool
_mongoc_error_is_network (const bson_error_t *error);

bool
_mongoc_error_is_server (bson_error_t *error);
Copy link
Contributor

Choose a reason for hiding this comment

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

Since error is not being modified, and is therefore not an out parameter, should this instead be const bson_error_t *error?

@@ -565,6 +567,43 @@ result_check (result_t *result,
goto done;
}
}

if (error_response) {
Copy link
Contributor

Choose a reason for hiding this comment

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

This isn't something that should block merging, but it looks like this function has grown to be pretty long. I wonder if we should start thinking of breaking it up into smaller pieces?

Copy link
Contributor

@kkloberdanz kkloberdanz 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! Just a couple of minor questions, neither of which should block merging. Although, I'm still getting up to speed on the codebase, so someone else might want to double check. Good job! 👍

Copy link
Collaborator

@kevinAlbs kevinAlbs left a comment

Choose a reason for hiding this comment

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

Great work. I suggest storing an array of error replies to give callers access to all server errors on a bulk write.

@galon1 galon1 requested a review from kevinAlbs November 11, 2022 21:03
@@ -1355,6 +1357,22 @@ _mongoc_write_result_merge (mongoc_write_result_t *result, /* IN */
result->n_writeConcernErrors++;
}

/* If a server error ocurred, then append the raw response to the
* error_replies array. */
Copy link
Member

Choose a reason for hiding this comment

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

Offhand, would the first { ok: 0 } command response (post-retry) completely interrupt a bulk write operation regardless of the ordered option (note: ordered: false is essentially continue-on-error).

Our specs are ambiguous about this (see: DRIVERS-2090, DRIVERS-2159).

I noted in the unified test runner code below, the assertion is only done on errorReplies.0, which assumes that three will only ever be on error reply. That's fine, as I intentionally wrote the tests with the above ambiguity in mind (see: mongodb/specifications@33a03f2.

But here, I'm more curious about whether multiple errorReplies are even possible in libmongoc. If not, are we just using an errorReplies array on the result for flexibility?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is possible for libmongoc to return multiple errorReplies. Here is a test displaying this behavior. Since ordered: false continues on error when the failPoint is hit twice, two errorReplies are returned by libmongoc, as well as other errors that occurred if they did (in the test a writeError also was raised).

Copy link
Member

Choose a reason for hiding this comment

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

Thanks for indulging my question. Looks like an oversight in the test runner syntax I introduced in DRIVERS-2385. I've made a note about this in DRIVERS-1547 as that's the most likely ticket we'd use to add spec test for multiple command failures in a bulk write.

@galon1 galon1 requested review from jmikola and kevinAlbs November 14, 2022 16:33
Copy link
Collaborator

@kevinAlbs kevinAlbs left a comment

Choose a reason for hiding this comment

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

LGTM with leak fixed. Great work.

@kevinAlbs kevinAlbs removed the request for review from vector-of-bool November 14, 2022 20:20

if (bson_iter_init_find (&iter, result->reply, "errorReplies")) {
bson_lookup_doc_null_ok (
result->reply, "errorReplies.0", &doc_to_match);
Copy link
Member

Choose a reason for hiding this comment

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

Continuing the conversation in #1144 (comment)

Sorry, but I misread bson_lookup_doc_null_ok and thought it gracefully allowed for missing values. I don't think there's any reason to use that, as it could still abort if the array is empty.

I could have sworn there was a function that allowed full field paths and gracefully handled missing keys. Perhaps I was thinking of bson_iter_find_descendant, which bson_lookup uses internally before it aborts on a failed resolution.

Perhaps it'd be best to use assert_match_bson() to check that "errorReplies.0" is a document. That function will emit a test error on failure, unlike ASSERT_MATCH(), which aborts. I believe you can use the $$type, although I don't know offhand if the function supports field paths (e.g. "errorReplies.0"), or if you might need to do something like:

{ "errorReplies": { "0": { "$$type": "object" } } }

/cc @kevinAlbs

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I just pushed changes that check if errorReplies.0 is a document. I ended up using BSON_ITER_HOLDS_DOCUMENT and BSON_ITER_HOLDS_ARRAY to check that errorReplies was the expected type. I thought to use these because that is how the reply is also checked right above my code (line 496 where error_labels_contain is checked).

@galon1 galon1 requested a review from jmikola November 15, 2022 17:20
Copy link
Member

@jmikola jmikola left a comment

Choose a reason for hiding this comment

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

Optional suggestion, but LGTM regardless.

@galon1 galon1 merged commit 6f46bc0 into mongodb:master Nov 16, 2022
@galon1 galon1 deleted the CDRIVER-4425 branch November 16, 2022 15:20
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