From a7a867c1e6f1bac339d8118c508818492acd316d Mon Sep 17 00:00:00 2001 From: Ben Darnell Date: Mon, 29 Aug 2016 05:35:19 +0800 Subject: [PATCH] raft: Allow an election immediately after start with checkQuorum Previously, the checkQuorum flag required an election timeout to expire before a node could cast its first vote. This change permits the node to cast a vote at any time when the leader is not known, including immediately after startup. --- raft/raft.go | 2 +- raft/raft_test.go | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/raft/raft.go b/raft/raft.go index 740c832b8..bc1a94db3 100644 --- a/raft/raft.go +++ b/raft/raft.go @@ -598,7 +598,7 @@ func (r *raft) Step(m pb.Message) error { lead := m.From if m.Type == pb.MsgVote { force := bytes.Equal(m.Context, []byte(campaignTransfer)) - inLease := r.checkQuorum && r.state != StateCandidate && r.electionElapsed < r.electionTimeout + inLease := r.checkQuorum && r.lead != None && r.electionElapsed < r.electionTimeout if !force && inLease { // If a server receives a RequestVote request within the minimum election timeout // of hearing from a current leader, it does not update its term or grant its vote diff --git a/raft/raft_test.go b/raft/raft_test.go index c0e66d3e7..a18c56715 100644 --- a/raft/raft_test.go +++ b/raft/raft_test.go @@ -1281,10 +1281,8 @@ func TestLeaderElectionWithCheckQuorum(t *testing.T) { setRandomizedElectionTimeout(a, a.electionTimeout+1) setRandomizedElectionTimeout(b, b.electionTimeout+2) - // Letting b's electionElapsed reach to timeout so that it can vote for a - for i := 0; i < b.electionTimeout; i++ { - b.tick() - } + // Immediately after creation, votes are cast regardless of the + // election timeout. nt.send(pb.Message{From: 1, To: 1, Type: pb.MsgHup}) if a.state != StateLeader {