summaryrefslogtreecommitdiff
path: root/internal/quorum
diff options
context:
space:
mode:
Diffstat (limited to 'internal/quorum')
-rw-r--r--internal/quorum/quorum.go35
-rw-r--r--internal/quorum/quorum_test.go23
2 files changed, 53 insertions, 5 deletions
diff --git a/internal/quorum/quorum.go b/internal/quorum/quorum.go
index d7fb866..79fea11 100644
--- a/internal/quorum/quorum.go
+++ b/internal/quorum/quorum.go
@@ -11,9 +11,10 @@ import (
)
type Quorum struct {
- conf config.Config
- votes map[string]vote.Vote
- voteCh chan vote.Vote
+ conf config.Config
+ votes map[string]vote.Vote
+ voteCh chan vote.Vote
+ prevLiveNodes []string
}
type Score struct {
@@ -38,11 +39,15 @@ func (quo Quorum) Start(ctx context.Context) <-chan []string {
for {
select {
case <-time.After(vote.Expiry):
- liveNodesCh <- quo.deleteExpiredVotes()
+ if liveNodes, changed := quo.liveNodes(); changed {
+ liveNodesCh <- liveNodes
+ }
case vote := <-quo.voteCh:
quo.vote(vote)
+ if liveNodes, changed := quo.liveNodes(); changed {
+ liveNodesCh <- liveNodes
+ }
quo.score()
- liveNodesCh <- quo.deleteExpiredVotes()
case <-ctx.Done():
return
}
@@ -94,6 +99,26 @@ func (quo Quorum) score() (scores []Score) {
return
}
+func (quo *Quorum) liveNodes() ([]string, bool) {
+ newLiveNodes := quo.deleteExpiredVotes()
+ defer func() { quo.prevLiveNodes = newLiveNodes }()
+
+ if len(newLiveNodes) != len(quo.prevLiveNodes) {
+ return newLiveNodes, true
+ }
+
+ for _, x := range newLiveNodes {
+ for _, y := range quo.prevLiveNodes {
+ if x == y {
+ continue
+ }
+ return newLiveNodes, false
+ }
+ }
+
+ return newLiveNodes, true
+}
+
func (quo Quorum) deleteExpiredVotes() (liveNodes []string) {
var expired []string
diff --git a/internal/quorum/quorum_test.go b/internal/quorum/quorum_test.go
index ac5cbc6..176a4fb 100644
--- a/internal/quorum/quorum_test.go
+++ b/internal/quorum/quorum_test.go
@@ -125,3 +125,26 @@ func TestExpire(t *testing.T) {
t.Errorf("Expected 'foo' to be the live node, but got : %v", liveNodes[0])
}
}
+
+func TestLiveNodes(t *testing.T) {
+ conf := config.Config{Nodes: []string{"foo:1234", "bay:4321"}}
+ quo := New(conf)
+
+ vote1 := vote.New(conf, " foo bar baz bay\n")
+ vote1.ExpiresAt = time.Now().Add(1 * time.Hour)
+ quo.vote(vote1)
+
+ vote2 := vote.New(conf, " bay foo bar baz\n")
+ vote2.ExpiresAt = time.Now().Add(1 * time.Hour)
+ quo.vote(vote2)
+
+ liveNodes, changed := quo.liveNodes()
+ if !changed {
+ t.Errorf("Expected live node list to be changed: %v", liveNodes)
+ }
+
+ liveNodes, changed = quo.liveNodes()
+ if changed {
+ t.Errorf("Expected live node list not to be changed: %v", liveNodes)
+ }
+}