-
Notifications
You must be signed in to change notification settings - Fork 4.5k
grpc: Fix cardinality violations in client streaming and unary RPCs. #8330
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
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #8330 +/- ##
==========================================
- Coverage 82.25% 82.20% -0.05%
==========================================
Files 417 419 +2
Lines 41356 42039 +683
==========================================
+ Hits 34017 34560 +543
- Misses 5923 6008 +85
- Partials 1416 1471 +55
🚀 New features to boost your workflow:
|
@Pranjali-2501 please use the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great, just a couple really small things. Thanks!
test/end2end_test.go
Outdated
@@ -3739,6 +3739,39 @@ func (s) TestClientStreaming_ReturnErrorAfterSendAndClose(t *testing.T) { | |||
} | |||
} | |||
|
|||
// Tests that a client receives a cardinality violation error for client-streaming | |||
// RPCs if the server call SendAndClose after calling SendAndClose. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// RPCs if the server call SendAndClose after calling SendAndClose. | |
// RPCs if the server calls SendAndClose multiple times. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
test/end2end_test.go
Outdated
t.Fatalf("stream.Send(_) = %v, want <nil>", err) | ||
} | ||
if _, err := stream.CloseAndRecv(); status.Code(err) != codes.Internal { | ||
t.Fatalf("stream.CloseAndRecv() = %v, want error %s", err, codes.Internal) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
t.Fatalf("stream.CloseAndRecv() = %v, want error %s", err, codes.Internal) | |
t.Fatalf("stream.CloseAndRecv() = %v, want error with status code %s", err, codes.Internal) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
stream.go
Outdated
@@ -1167,7 +1167,7 @@ func (a *csAttempt) recvMsg(m any, payInfo *payloadInfo) (err error) { | |||
} else if err != nil { | |||
return toRPCErr(err) | |||
} | |||
return toRPCErr(errors.New("grpc: client streaming protocol violation: get <nil>, want <EOF>")) | |||
return status.Errorf(codes.Internal, "client streaming cardinality violation: get <nil>, want <EOF>") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a similar method on addrConnStream
that also needs to be updated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM with minor comments.
test/end2end_test.go
Outdated
func (s) TestClientStreaming_ServerHandlerSendAndCloseAfterSendAndClose(t *testing.T) { | ||
ss := stubserver.StubServer{ | ||
StreamingInputCallF: func(stream testgrpc.TestService_StreamingInputCallServer) error { | ||
if err := stream.SendAndClose(&testpb.StreamingInputCallResponse{}); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In my opinion, we should call Send
instead of SendAndClose
. SendAndClose
doesn't actually close the stream, but it can confuse readers why the server didn't get an error when trying to write to a closed stream.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SendAndClose() have been used for all client-streaming test cases. To maintain the consistency, I have used SendAndClose() in new tests.
If all occurrences of SendAndClose() needs to be replaced by Send(), I'll do that in a separate PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Existing refferences use SendAndClose
probably because the intention is to close the stream (even though closing doesn't happen until the handler returns). This is not done for consistency. In this test, we want to send multiple message and not close, so I would suggest just changing this test to use Close()
. We don't need to change the remaining tests. Both Send
and SendAndClose
are part of the stable API.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Send()
method is not defined in StreamingInputCall
. So I have used SendMsg() instead of Send().
Let me know if you want me to use Send() only. I will then change the complete test.
stream.go
Outdated
@@ -1167,7 +1167,7 @@ func (a *csAttempt) recvMsg(m any, payInfo *payloadInfo) (err error) { | |||
} else if err != nil { | |||
return toRPCErr(err) | |||
} | |||
return toRPCErr(errors.New("grpc: client streaming protocol violation: get <nil>, want <EOF>")) | |||
return status.Errorf(codes.Internal, "client streaming cardinality violation: get <nil>, want <EOF>") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can improve this error message to say something like:
cardinality violation: expected EOF from non-streaming server, but received another message
. I believe this can also happen in unary RPCs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The message still says "" instead of "another message". When a user sees "got nil", they would need to lookup the implementation to understand what it means. If we say "another message", the failure condition is clearer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Made the changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approving.
Client should ensure an
INTERNAL
error is returned for non-server streaming RPCs if the server attempts to send more than one response.Currently it is returning
UNKNOWN
, which should not be the case for cardinality violations.Filed in #7286
RELEASE NOTES: