From cc304ac03c70eb641c57a7acb3b21ec4a2f6b126 Mon Sep 17 00:00:00 2001 From: Gyu-Ho Lee Date: Wed, 2 Nov 2016 21:36:27 -0700 Subject: [PATCH] etcdserver: translate EOF to ErrNoLeader for renew, timetolive Address https://github.com/coreos/etcd/issues/6754. In case there are network errors or unexpected EOF errors in TimeToLive http requests to leader, we translate that into ErrNoLeader, and expects the client to retry its request. --- etcdserver/v3_server.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/etcdserver/v3_server.go b/etcdserver/v3_server.go index 1eaa90dc8..55a1d764c 100644 --- a/etcdserver/v3_server.go +++ b/etcdserver/v3_server.go @@ -17,6 +17,7 @@ package etcdserver import ( "bytes" "encoding/binary" + "io" "strconv" "strings" "time" @@ -326,6 +327,7 @@ func (s *EtcdServer) LeaseRenew(id lease.LeaseID) (int64, error) { if err == nil { break } + err = convertEOFToNoLeader(err) } return ttl, err } @@ -363,10 +365,23 @@ func (s *EtcdServer) LeaseTimeToLive(ctx context.Context, r *pb.LeaseTimeToLiveR if err == nil { return iresp.LeaseTimeToLiveResponse, nil } + err = convertEOFToNoLeader(err) } return nil, err } +// convertEOFToNoLeader converts EOF erros to ErrNoLeader because +// lease renew, timetolive requests to followers are forwarded to leader, +// and follower might not be able to reach leader from transient network +// errors (often EOF errors). By returning ErrNoLeader, signal clients +// to retry its requests. +func convertEOFToNoLeader(err error) error { + if err == io.EOF || err == io.ErrUnexpectedEOF { + return ErrNoLeader + } + return err +} + func (s *EtcdServer) waitLeader() (*membership.Member, error) { leader := s.cluster.Member(s.Leader()) for i := 0; i < 5 && leader == nil; i++ {