diff --git a/clientv3/retry.go b/clientv3/retry.go index 2f2af774c..e6d17d032 100644 --- a/clientv3/retry.go +++ b/clientv3/retry.go @@ -32,7 +32,7 @@ type retryStopErrFunc func(error) bool func isRepeatableStopError(err error) bool { eErr := rpctypes.Error(err) // always stop retry on etcd errors - if _, ok := eErr.(rpctypes.EtcdError); ok { + if serverErr, ok := eErr.(rpctypes.EtcdError); ok && serverErr.Code() != codes.Unavailable { return true } // only retry if unavailable @@ -62,11 +62,16 @@ func (c *Client) newRetryWrapper(isStop retryStopErrFunc) retryRPCFunc { if logger.V(4) { logger.Infof("clientv3/retry: error %q on pinned endpoint %q", err.Error(), pinned) } - // mark this before endpoint switch is triggered - c.balancer.hostPortError(pinned, err) - if s, ok := status.FromError(err); ok && s.Code() == codes.Unavailable { + + if s, ok := status.FromError(err); ok && (s.Code() == codes.Unavailable || s.Code() == codes.DeadlineExceeded || s.Code() == codes.Internal) { + // mark this before endpoint switch is triggered + c.balancer.hostPortError(pinned, err) c.balancer.next() + if logger.V(4) { + logger.Infof("clientv3/retry: switching from %q due to error %q", pinned, err.Error()) + } } + if isStop(err) { return err }