mirror of https://github.com/grpc/grpc-go.git
addrConn: set ac.state to TransientFailure upon non-temporary errors (#1657)
So failfast RPCs will fail with unavailable errors when this happens.
This commit is contained in:
parent
87bcb38fba
commit
409fd8e23b
|
@ -966,6 +966,12 @@ func (ac *addrConn) resetTransport() error {
|
|||
newTransport, err := transport.NewClientTransport(ac.cc.ctx, sinfo, copts, timeout)
|
||||
if err != nil {
|
||||
if e, ok := err.(transport.ConnectionError); ok && !e.Temporary() {
|
||||
ac.mu.Lock()
|
||||
if ac.state != connectivity.Shutdown {
|
||||
ac.state = connectivity.TransientFailure
|
||||
ac.cc.handleSubConnStateChange(ac.acbw, ac.state)
|
||||
}
|
||||
ac.mu.Unlock()
|
||||
return err
|
||||
}
|
||||
grpclog.Warningf("grpc: addrConn.resetTransport failed to create client transport: %v; Reconnecting to %v", err, addr)
|
||||
|
|
|
@ -4340,6 +4340,50 @@ func TestCredsHandshakeAuthority(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
type clientFailCreds struct {
|
||||
got string
|
||||
}
|
||||
|
||||
func (c *clientFailCreds) ServerHandshake(rawConn net.Conn) (net.Conn, credentials.AuthInfo, error) {
|
||||
return rawConn, nil, nil
|
||||
}
|
||||
func (c *clientFailCreds) ClientHandshake(ctx context.Context, authority string, rawConn net.Conn) (net.Conn, credentials.AuthInfo, error) {
|
||||
return nil, nil, fmt.Errorf("client handshake fails with fatal error")
|
||||
}
|
||||
func (c *clientFailCreds) Info() credentials.ProtocolInfo {
|
||||
return credentials.ProtocolInfo{}
|
||||
}
|
||||
func (c *clientFailCreds) Clone() credentials.TransportCredentials {
|
||||
return c
|
||||
}
|
||||
func (c *clientFailCreds) OverrideServerName(s string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// This test makes sure that failfast RPCs fail if client handshake fails with
|
||||
// fatal errors.
|
||||
func TestFailfastRPCFailOnFatalHandshakeError(t *testing.T) {
|
||||
lis, err := net.Listen("tcp", "localhost:0")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to listen: %v", err)
|
||||
}
|
||||
defer lis.Close()
|
||||
|
||||
cc, err := grpc.Dial("passthrough:///"+lis.Addr().String(), grpc.WithTransportCredentials(&clientFailCreds{}))
|
||||
if err != nil {
|
||||
t.Fatalf("grpc.Dial(_) = %v", err)
|
||||
}
|
||||
defer cc.Close()
|
||||
|
||||
tc := testpb.NewTestServiceClient(cc)
|
||||
// This unary call should fail, but not timeout.
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
||||
defer cancel()
|
||||
if _, err := tc.EmptyCall(ctx, &testpb.Empty{}, grpc.FailFast(true)); grpc.Code(err) != codes.Unavailable {
|
||||
t.Fatalf("TestService/EmptyCall(_, _) = _, %v, want <Unavailable>", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFlowControlLogicalRace(t *testing.T) {
|
||||
// Test for a regression of https://github.com/grpc/grpc-go/issues/632,
|
||||
// and other flow control bugs.
|
||||
|
|
Loading…
Reference in New Issue