From 9a4b2bdcccd94bfb5e67121f34a54fcd0eade458 Mon Sep 17 00:00:00 2001 From: Piotr Tabor Date: Thu, 22 Apr 2021 12:57:23 +0200 Subject: [PATCH] Errors: `context cancelled` or `context deadline exceeded` are exposed as codes.Canceled, codes.DeadlineExceeded instead of 'codes.Unknown' --- CHANGELOG-3.5.md | 1 + api/v3rpc/rpctypes/error.go | 3 +++ server/etcdserver/api/v3rpc/util.go | 4 ++++ tests/integration/clientv3/util.go | 3 ++- 4 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG-3.5.md b/CHANGELOG-3.5.md index 81e825137..45db3a171 100644 --- a/CHANGELOG-3.5.md +++ b/CHANGELOG-3.5.md @@ -70,6 +70,7 @@ See [code changes](https://github.com/etcd-io/etcd/compare/v3.4.0...v3.5.0) and - [ETCD_CLIENT_DEBUG env](https://github.com/etcd-io/etcd/pull/12786): Now supports log levels (debug, info, warn, error, dpanic, panic, fatal). Only when set, overrides application-wide grpc logging settings. - [Embed Etcd.Close()](https://github.com/etcd-io/etcd/pull/12828) needs to called exactly once and closes Etcd.Err() stream. - [Embed Etcd does not override global/grpc logger](https://github.com/etcd-io/etcd/pull/12861) be default any longer. If desired, please call `embed.Config::SetupGlobalLoggers()` explicitly. +- Errors: `context cancelled` or `context deadline exceeded` are exposed as codes.Canceled, codes.DeadlineExceeded instead of 'codes.Unknown'. ### - Make sure [save snapshot downloads checksum for integrity checks](https://github.com/etcd-io/etcd/pull/11896). diff --git a/api/v3rpc/rpctypes/error.go b/api/v3rpc/rpctypes/error.go index 24fdc8573..c03e91cfb 100644 --- a/api/v3rpc/rpctypes/error.go +++ b/api/v3rpc/rpctypes/error.go @@ -84,6 +84,9 @@ var ( ErrGRPCDowngradeInProcess = status.New(codes.FailedPrecondition, "etcdserver: cluster has a downgrade job in progress").Err() ErrGRPCNoInflightDowngrade = status.New(codes.FailedPrecondition, "etcdserver: no inflight downgrade job").Err() + ErrGRPCCanceled = status.New(codes.Canceled, "etcdserver: request canceled").Err() + ErrGRPCDeadlineExceeded = status.New(codes.DeadlineExceeded, "etcdserver: context deadline exceeded").Err() + errStringToError = map[string]error{ ErrorDesc(ErrGRPCEmptyKey): ErrGRPCEmptyKey, ErrorDesc(ErrGRPCKeyNotFound): ErrGRPCKeyNotFound, diff --git a/server/etcdserver/api/v3rpc/util.go b/server/etcdserver/api/v3rpc/util.go index dc6e0271f..51cbdc66a 100644 --- a/server/etcdserver/api/v3rpc/util.go +++ b/server/etcdserver/api/v3rpc/util.go @@ -83,6 +83,10 @@ var toGRPCErrorMap = map[error]error{ auth.ErrAuthNotEnabled: rpctypes.ErrGRPCAuthNotEnabled, auth.ErrInvalidAuthToken: rpctypes.ErrGRPCInvalidAuthToken, auth.ErrInvalidAuthMgmt: rpctypes.ErrGRPCInvalidAuthMgmt, + + // In sync with status.FromContextError + context.Canceled: rpctypes.ErrGRPCCanceled, + context.DeadlineExceeded: rpctypes.ErrGRPCDeadlineExceeded, } func togRPCError(err error) error { diff --git a/tests/integration/clientv3/util.go b/tests/integration/clientv3/util.go index 674a5d1c8..26ee793c9 100644 --- a/tests/integration/clientv3/util.go +++ b/tests/integration/clientv3/util.go @@ -50,7 +50,8 @@ func IsServerCtxTimeout(err error) bool { return false } code := ev.Code() - return code == codes.DeadlineExceeded && strings.Contains(err.Error(), "context deadline exceeded") + return (code == codes.DeadlineExceeded /*3.5+"*/ || code == codes.Unknown /*<=3.4*/) && + strings.Contains(err.Error(), "context deadline exceeded") } // IsClientTimeout checks reason of the error.