From 00b31512a1bc6358ba656952004e743e66afd8eb Mon Sep 17 00:00:00 2001 From: Benjamin Wang Date: Fri, 13 Jan 2023 15:17:19 +0800 Subject: [PATCH] etcdserver: return membership.ErrIDNotFound when the memberID not found Backport https://github.com/etcd-io/etcd/pull/15095 to 3.4. When promoting a learner, we need to wait until the leader's applied ID catches up to the commitId. Afterwards, check whether the learner ID exist or not, and return `membership.ErrIDNotFound` directly in the API if the member ID not found, to avoid the request being unnecessarily delivered to raft. Signed-off-by: Benjamin Wang --- etcdserver/server.go | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/etcdserver/server.go b/etcdserver/server.go index 808f8c9df..d24963f9d 100644 --- a/etcdserver/server.go +++ b/etcdserver/server.go @@ -1798,6 +1798,10 @@ func (s *EtcdServer) mayPromoteMember(id types.ID) error { // Note: it will return nil if member is not found in cluster or if member is not learner. // These two conditions will be checked before apply phase later. func (s *EtcdServer) isLearnerReady(id uint64) error { + if err := s.waitAppliedIndex(); err != nil { + return err + } + rs := s.raftStatus() // leader's raftStatus.Progress is not nil @@ -1817,12 +1821,16 @@ func (s *EtcdServer) isLearnerReady(id uint64) error { } } - if isFound { - leaderMatch := rs.Progress[leaderID].Match - // the learner's Match not caught up with leader yet - if float64(learnerMatch) < float64(leaderMatch)*readyPercent { - return ErrLearnerNotReady - } + // We should return an error in API directly, to avoid the request + // being unnecessarily delivered to raft. + if !isFound { + return membership.ErrIDNotFound + } + + leaderMatch := rs.Progress[leaderID].Match + // the learner's Match not caught up with leader yet + if float64(learnerMatch) < float64(leaderMatch)*readyPercent { + return ErrLearnerNotReady } return nil