Browse Source

Merge pull request #6791 from gyuho/grpc-leader

etcdserver: translate EOF to ErrNoLeader for renew, timetolive
Gyu-Ho Lee 9 years ago
parent
commit
bbc1cdafef
1 changed files with 15 additions and 0 deletions
  1. 15 0
      etcdserver/v3_server.go

+ 15 - 0
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++ {