More robust testing, TestSplitVotes
This commit is contained in:
24
candidate.go
24
candidate.go
@@ -5,6 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -34,9 +35,7 @@ type CandidateState int
|
||||
const (
|
||||
StateLeader CandidateState = iota
|
||||
StateNotLeader
|
||||
)
|
||||
|
||||
const (
|
||||
maxVotePeriod = 5 * time.Second
|
||||
voteTimeout = 10 * time.Second
|
||||
leadershipWait = 15 * time.Second
|
||||
@@ -44,6 +43,11 @@ const (
|
||||
maxFastVotePeriod = 100 * time.Millisecond
|
||||
)
|
||||
|
||||
var StateName = map[CandidateState]string{
|
||||
StateLeader: "LEADER",
|
||||
StateNotLeader: "NOT_LEADER",
|
||||
}
|
||||
|
||||
func NewCandidate(numVoters int, signingKey string) *Candidate {
|
||||
change := make(chan CandidateState, 100)
|
||||
|
||||
@@ -182,12 +186,23 @@ func (c *Candidate) elect(v *vote) {
|
||||
defer c.mu.Unlock()
|
||||
|
||||
state := StateNotLeader
|
||||
no := 0
|
||||
yes := 0
|
||||
|
||||
defer func() {
|
||||
if c.state == state {
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf(
|
||||
"[elect] transitioning %s -> %s (no=%d yes=%d min_yes=%d)",
|
||||
StateName[c.state],
|
||||
StateName[state],
|
||||
no,
|
||||
yes,
|
||||
c.numVoters/2+1,
|
||||
)
|
||||
|
||||
c.state = state
|
||||
c.c <- state
|
||||
}()
|
||||
@@ -197,9 +212,6 @@ func (c *Candidate) elect(v *vote) {
|
||||
c.votes[v.VoterID] = v
|
||||
}
|
||||
|
||||
no := 0
|
||||
yes := 0
|
||||
|
||||
for key, vote := range c.votes {
|
||||
if time.Since(vote.received) > voteTimeout {
|
||||
// Remove stale vote from consideration
|
||||
@@ -220,7 +232,7 @@ func (c *Candidate) elect(v *vote) {
|
||||
yes++
|
||||
}
|
||||
|
||||
if no > 0 || yes <= c.numVoters/2 {
|
||||
if no > 0 || yes < c.numVoters/2+1 {
|
||||
// We lost the vote
|
||||
c.firstYes = time.Time{}
|
||||
state = StateNotLeader
|
||||
|
||||
Reference in New Issue
Block a user