Skip to content
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

Flatten RPCError causes if they're also RPCErrors with the same code #2083

Merged
merged 7 commits into from
Oct 9, 2024

Conversation

gjcairo
Copy link
Collaborator

@gjcairo gjcairo commented Oct 6, 2024

Motivation

For errors happening deep in the task tree, we'd wrap them in many layers of RPCErrors. This isn't particularly nice.

Modifications

This PR changes the behaviour of the RPCError initialiser to flatten the cause as long as it's an RPCError with the same status code as the wrapping error.

Result

Friendlier errors.

@gjcairo gjcairo added semver/minor Adds new public API. v2 A change for v2 labels Oct 6, 2024
@gjcairo gjcairo requested a review from glbrntt October 6, 2024 16:58
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I also migrated this to swift-testing since I was adding new tests

var finalMessage = message
var finalMetadata = metadata
var nextCause = cause
while let nextRPCErrorCause = nextCause as? RPCError {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't think we should do this in a loop. Consider:

let error1 = RPCError(code: .unavailable, message: "error1")
let error2 = RPCError(code: .unavailable, message: "error2", cause: error1, flatteningCauses: false)
let error3 = RPCError(code: .unavailable, message: "error3", cause: error2, flatteningCauses: true)

Creating error3 would flatten the whole tree, even though error2 didn't want to be flattened.

I also don't know whether it makes sense to expose this as an option. Is there any reason we shouldn't unconditionally do this if the cause is an RPCError and the code matches?

Also, I think we should overload the init with a cause: RPCError so we don't have to pay for the cast if we're already holding the RPCError.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I can't really think of a reason why we wouldn't want to do this unconditionally other than flattening may potentially be expensive since we're creating new errors and dealing with strings.

If we do it unconditionally, then the loop would be unnecessary because all underlying causes would have been flattened already anyways.

And yeah good idea about the overload.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I can't really think of a reason why we wouldn't want to do this unconditionally other than flattening may potentially be expensive since we're creating new errors and dealing with strings.

We're already creating a new RPCError so that part isn't an issue. Strings a potentially expensive but that's the tradeoff for more info I guess.

If we do it unconditionally, then the loop would be unnecessary because all underlying causes would have been flattened already anyways.

Correct.

We can always add an opt-out later if we think it's necessary.

Tests/GRPCCoreTests/RPCErrorTests.swift Outdated Show resolved Hide resolved
@gjcairo gjcairo requested a review from glbrntt October 7, 2024 14:33
glbrntt pushed a commit that referenced this pull request Oct 7, 2024
## Motivation
We want to be able to flatten `RPCError`s, and to do so we need to be
able to merge the `Metadata` contained in each.

## Modifications
This PR adds a helper function to merge one `Metadata` instance into
another.

## Result
Unblocks #2083 and also provides
a potentially useful API for users.

**- Note:** Because of the way `Metadata` has been implemented, we can
have multiple _identical_ key-value pairs. This isn't ideal, as it's
particularly feasible that we'll end up with multiple repeated identical
pairs when merging two `Metadata`s. I think we should reconsider the
backing data structure (using a set for example) or add a check before
inserting to avoid this.
Sources/GRPCCore/RPCError.swift Outdated Show resolved Hide resolved
Tests/GRPCCoreTests/RPCErrorTests.swift Show resolved Hide resolved
@gjcairo gjcairo changed the title Add option to flatten RPCError causes Flatten RPCError causes if they're also RPCErrors with the same code Oct 9, 2024
Copy link
Collaborator

@glbrntt glbrntt left a comment

Choose a reason for hiding this comment

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

LGTM, thanks Gus!

@gjcairo gjcairo merged commit ce25e2c into grpc:main Oct 9, 2024
5 of 8 checks passed
@gjcairo gjcairo deleted the rpcerror-flatten branch October 9, 2024 09:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
semver/minor Adds new public API. v2 A change for v2
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants