clientv3: add "IsConnCanceled", deprecate "grpc.ErrClientConnClosing"
Signed-off-by: Gyuho Lee <gyuhox@gmail.com>
This commit is contained in:
@ -614,6 +614,26 @@ func canceledByCaller(stopCtx context.Context, err error) bool {
|
|||||||
return err == context.Canceled || err == context.DeadlineExceeded
|
return err == context.Canceled || err == context.DeadlineExceeded
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsConnCanceled returns true, if error is from a closed gRPC connection.
|
||||||
|
// ref. https://github.com/grpc/grpc-go/pull/1854
|
||||||
|
func IsConnCanceled(err error) bool {
|
||||||
|
if err == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// >= gRPC v1.10.x
|
||||||
|
s, ok := status.FromError(err)
|
||||||
|
if ok {
|
||||||
|
// connection is canceled or server has already closed the connection
|
||||||
|
return s.Code() == codes.Canceled || s.Message() == "transport is closing"
|
||||||
|
}
|
||||||
|
// >= gRPC v1.10.x
|
||||||
|
if err == context.Canceled {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// <= gRPC v1.7.x returns 'errors.New("grpc: the client connection is closing")'
|
||||||
|
return strings.Contains(err.Error(), "grpc: the client connection is closing")
|
||||||
|
}
|
||||||
|
|
||||||
func getHost(ep string) string {
|
func getHost(ep string) string {
|
||||||
url, uerr := url.Parse(ep)
|
url, uerr := url.Parse(ep)
|
||||||
if uerr != nil || !strings.Contains(ep, "://") {
|
if uerr != nil || !strings.Contains(ep, "://") {
|
||||||
|
@ -87,11 +87,16 @@
|
|||||||
// go func() { cli.Close() }()
|
// go func() { cli.Close() }()
|
||||||
// _, err := kvc.Get(ctx, "a")
|
// _, err := kvc.Get(ctx, "a")
|
||||||
// if err != nil {
|
// if err != nil {
|
||||||
|
// // with etcd clientv3 <= v3.3
|
||||||
// if err == context.Canceled {
|
// if err == context.Canceled {
|
||||||
// // grpc balancer calls 'Get' with an inflight client.Close
|
// // grpc balancer calls 'Get' with an inflight client.Close
|
||||||
// } else if err == grpc.ErrClientConnClosing {
|
// } else if err == grpc.ErrClientConnClosing {
|
||||||
// // grpc balancer calls 'Get' after client.Close.
|
// // grpc balancer calls 'Get' after client.Close.
|
||||||
// }
|
// }
|
||||||
|
// // with etcd clientv3 >= v3.4
|
||||||
|
// if clientv3.IsConnCanceled(err) {
|
||||||
|
// // gRPC client connection is closed
|
||||||
|
// }
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
package clientv3
|
package clientv3
|
||||||
|
@ -442,7 +442,7 @@ func TestKVGetErrConnClosed(t *testing.T) {
|
|||||||
go func() {
|
go func() {
|
||||||
defer close(donec)
|
defer close(donec)
|
||||||
_, err := cli.Get(context.TODO(), "foo")
|
_, err := cli.Get(context.TODO(), "foo")
|
||||||
if err != nil && err != context.Canceled && err != grpc.ErrClientConnClosing {
|
if !clientv3.IsConnCanceled(err) {
|
||||||
t.Fatalf("expected %v or %v, got %v", context.Canceled, grpc.ErrClientConnClosing, err)
|
t.Fatalf("expected %v or %v, got %v", context.Canceled, grpc.ErrClientConnClosing, err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
@ -474,7 +474,7 @@ func TestKVNewAfterClose(t *testing.T) {
|
|||||||
donec := make(chan struct{})
|
donec := make(chan struct{})
|
||||||
go func() {
|
go func() {
|
||||||
_, err := cli.Get(context.TODO(), "foo")
|
_, err := cli.Get(context.TODO(), "foo")
|
||||||
if err != context.Canceled && err != grpc.ErrClientConnClosing {
|
if !clientv3.IsConnCanceled(err) {
|
||||||
t.Fatalf("expected %v or %v, got %v", context.Canceled, grpc.ErrClientConnClosing, err)
|
t.Fatalf("expected %v or %v, got %v", context.Canceled, grpc.ErrClientConnClosing, err)
|
||||||
}
|
}
|
||||||
close(donec)
|
close(donec)
|
||||||
|
@ -296,7 +296,7 @@ func TestLeaseGrantErrConnClosed(t *testing.T) {
|
|||||||
go func() {
|
go func() {
|
||||||
defer close(donec)
|
defer close(donec)
|
||||||
_, err := cli.Grant(context.TODO(), 5)
|
_, err := cli.Grant(context.TODO(), 5)
|
||||||
if err != nil && err != grpc.ErrClientConnClosing && err != context.Canceled {
|
if !clientv3.IsConnCanceled(err) {
|
||||||
// grpc.ErrClientConnClosing if grpc-go balancer calls 'Get' after client.Close.
|
// grpc.ErrClientConnClosing if grpc-go balancer calls 'Get' after client.Close.
|
||||||
// context.Canceled if grpc-go balancer calls 'Get' with an inflight client.Close.
|
// context.Canceled if grpc-go balancer calls 'Get' with an inflight client.Close.
|
||||||
t.Fatalf("expected %v, %v or server unavailable, got %v", err != context.Canceled, grpc.ErrClientConnClosing, err)
|
t.Fatalf("expected %v, %v or server unavailable, got %v", err != context.Canceled, grpc.ErrClientConnClosing, err)
|
||||||
@ -328,7 +328,8 @@ func TestLeaseGrantNewAfterClose(t *testing.T) {
|
|||||||
|
|
||||||
donec := make(chan struct{})
|
donec := make(chan struct{})
|
||||||
go func() {
|
go func() {
|
||||||
if _, err := cli.Grant(context.TODO(), 5); err != context.Canceled && err != grpc.ErrClientConnClosing {
|
_, err := cli.Grant(context.TODO(), 5)
|
||||||
|
if !clientv3.IsConnCanceled(err) {
|
||||||
t.Fatalf("expected %v, %v or server unavailable, got %v", err != context.Canceled, grpc.ErrClientConnClosing, err)
|
t.Fatalf("expected %v, %v or server unavailable, got %v", err != context.Canceled, grpc.ErrClientConnClosing, err)
|
||||||
}
|
}
|
||||||
close(donec)
|
close(donec)
|
||||||
@ -360,7 +361,8 @@ func TestLeaseRevokeNewAfterClose(t *testing.T) {
|
|||||||
|
|
||||||
donec := make(chan struct{})
|
donec := make(chan struct{})
|
||||||
go func() {
|
go func() {
|
||||||
if _, err := cli.Revoke(context.TODO(), leaseID); err != context.Canceled && err != grpc.ErrClientConnClosing {
|
_, err := cli.Revoke(context.TODO(), leaseID)
|
||||||
|
if !clientv3.IsConnCanceled(err) {
|
||||||
t.Fatalf("expected %v, %v or server unavailable, got %v", err != context.Canceled, grpc.ErrClientConnClosing, err)
|
t.Fatalf("expected %v, %v or server unavailable, got %v", err != context.Canceled, grpc.ErrClientConnClosing, err)
|
||||||
}
|
}
|
||||||
close(donec)
|
close(donec)
|
||||||
|
Reference in New Issue
Block a user