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

client: improve connection errors from RPCs and Dial WithReturnConnectionError #4190

Closed
wants to merge 3 commits into from

Conversation

avalchev94
Copy link

@avalchev94 avalchev94 commented Feb 4, 2021

This is the implementation regarding issue-4163. I didn't follow the instructions, because it involved a lot more code changes. Implementation tries to copy the same approach used in ClientConn error saving.

Fixes #4163

@avalchev94 avalchev94 marked this pull request as ready for review February 4, 2021 22:07
@dfawley dfawley self-requested a review February 5, 2021 00:37
@dfawley dfawley self-assigned this Feb 5, 2021
@dfawley dfawley added the Type: Feature New features or improvements in behavior label Feb 5, 2021
@dfawley dfawley added this to the 1.36 Release milestone Feb 5, 2021
Copy link
Member

@dfawley dfawley left a comment

Choose a reason for hiding this comment

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

Thank you for the PR! Comments inline.

@@ -1309,6 +1312,7 @@ func (t *http2Client) reader() {
// Check the validity of server preface.
frame, err := t.framer.fr.ReadFrame()
if err != nil {
t.updateConnectionError(err)
Copy link
Member

Choose a reason for hiding this comment

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

One thing about my design in #4163 that I preferred is that adding an error to Close means we're forced to inspect every place it is called (now and in the future) so we can improve our error reporting in all instances where the transport is closed. With this alternate implementation, we only optionally improve it. I'm fine with the LastConnectionError() method (though it is stateful, and, as such, I do prefer the alternative of making OnClose accept an error result). But we should really make http2Client.Close accept an error. If there is no useful error at the site where Close is called, just pass ErrConnClosing.

If we do that, we also know that whenever OnClose is called, there must be a non-nil error, and we can simplify the clientconn.go code to always return nil, nil, t.LastConnectionError() (without the nil check).

Copy link
Author

Choose a reason for hiding this comment

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

Ok, I will go with your idea. Should I keep LastConnectionError or have onClose callback to receive the connection error as parameter?

Copy link
Member

Choose a reason for hiding this comment

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

LastConnectionError is stateful, meaning it requires synchronization and opens the possibility for a new class of bugs. I think if OnClose takes an error to pass the information, it makes for a better flow. (This is "share memory by communicating instead of communicating by sharing memory," it just doesn't require a channel.)


c.validCert, err = c.generateCert(ca, time.Now().Add(time.Hour))
if err != nil {
return fmt.Errorf("failed to generate valid cert: %v", err)
Copy link
Member

Choose a reason for hiding this comment

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

You should be able to simplify things significantly by just panicking whenever an error happens inside generateCert. Failing "gracefully" for something we expect to pass, during initialization, isn't important.

Comment on lines +682 to +683
clientCerts := clientCertificates{}
if err := clientCerts.generateCertificates(&ca); err != nil {
Copy link
Member

Choose a reason for hiding this comment

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

Combine these into clientCerts, err := newClientCertificates(&ca)?

creds := credentials.NewTLS(cfg)

dialCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
cc, err := grpc.DialContext(
Copy link
Member

Choose a reason for hiding this comment

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

Can you please also add a check for RPC errors:

cc, err := grpc.Dial(.../* no WithBlock or WithReturnConnectionError*/)
...
client := testpb.NewTestServiceClient(cc)
res, err := client.EmptyCall(...)
// Ensure err contains the connection error

You should be able to use the stubserver.StubServer to make it easy to create the client and server (server and dial options can be provided to the Start method); check the other tests for examples.

Copy link
Member

@dfawley dfawley left a comment

Choose a reason for hiding this comment

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

Thank you for the PR! Comments inline.

@dfawley dfawley changed the title http2Client: save last connection error client: improve connection errors from RPCs and Dial WithReturnConnectionError Feb 5, 2021
@easwars easwars modified the milestones: 1.36 Release, 1.37 Release Feb 10, 2021
@dfawley dfawley assigned avalchev94 and unassigned dfawley Feb 11, 2021
@stale
Copy link

stale bot commented Feb 21, 2021

This issue is labeled as requiring an update from the reporter, and no update has been received after 6 days. If no update is provided in the next 7 days, this issue will be automatically closed.

@stale stale bot added the stale label Feb 21, 2021
@easwars easwars closed this Mar 18, 2021
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Sep 15, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Surface TLS errors to RPC errors
3 participants