Election!
This commit is contained in:
@@ -71,6 +71,10 @@ func (c *Candidate) State() CandidateState {
|
|||||||
return c.state
|
return c.state
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Candidate) IsLeader() bool {
|
||||||
|
return c.State() == StateLeader
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Candidate) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
func (c *Candidate) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
if r.Method != http.MethodPost {
|
if r.Method != http.MethodPost {
|
||||||
http.Error(
|
http.Error(
|
||||||
@@ -137,6 +141,8 @@ func (c *Candidate) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
|
||||||
enc := json.NewEncoder(w)
|
enc := json.NewEncoder(w)
|
||||||
|
|
||||||
err = enc.Encode(c.resp)
|
err = enc.Encode(c.resp)
|
||||||
|
|||||||
42
elect_test.go
Normal file
42
elect_test.go
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package elect_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/gopatchy/elect"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSimple(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
c := elect.NewCandidate(1, "abc123")
|
||||||
|
|
||||||
|
defer c.Stop()
|
||||||
|
|
||||||
|
listener, err := net.ListenTCP("tcp", nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
srv := &http.Server{
|
||||||
|
Handler: c,
|
||||||
|
ReadHeaderTimeout: 30 * time.Second,
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
err := srv.Serve(listener)
|
||||||
|
require.ErrorIs(t, err, http.ErrServerClosed)
|
||||||
|
}()
|
||||||
|
|
||||||
|
defer srv.Close()
|
||||||
|
|
||||||
|
v := elect.NewVoter(fmt.Sprintf("http://%s/", listener.Addr()), "abc123")
|
||||||
|
require.NotNil(t, v)
|
||||||
|
|
||||||
|
defer v.Stop()
|
||||||
|
|
||||||
|
require.Eventually(t, c.IsLeader, 15*time.Second, 100*time.Millisecond)
|
||||||
|
}
|
||||||
3
voter.go
3
voter.go
@@ -77,7 +77,7 @@ func (v *Voter) loop(update <-chan time.Duration, done chan<- bool) {
|
|||||||
func (v *Voter) poll(update <-chan time.Duration, t *time.Ticker) bool {
|
func (v *Voter) poll(update <-chan time.Duration, t *time.Ticker) bool {
|
||||||
t2 := &time.Timer{}
|
t2 := &time.Timer{}
|
||||||
|
|
||||||
if v.vote.NumPollsSinceChange < 10 {
|
if v.vote.NumPollsSinceChange < 11 {
|
||||||
t2 = time.NewTimer(100 * time.Millisecond)
|
t2 = time.NewTimer(100 * time.Millisecond)
|
||||||
defer t2.Stop()
|
defer t2.Stop()
|
||||||
}
|
}
|
||||||
@@ -110,6 +110,7 @@ func (v *Voter) sendVote() {
|
|||||||
|
|
||||||
resp, err := v.client.R().
|
resp, err := v.client.R().
|
||||||
SetHeader("Signature", mac(js, v.signingKey)).
|
SetHeader("Signature", mac(js, v.signingKey)).
|
||||||
|
SetHeader("Content-Type", "application/json").
|
||||||
SetBody(js).
|
SetBody(js).
|
||||||
SetResult(vr).
|
SetResult(vr).
|
||||||
Post("")
|
Post("")
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
package elect_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/gopatchy/elect"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestNew(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
v := elect.NewVoter("https://[::1]:1234", "abc123")
|
|
||||||
require.NotNil(t, v)
|
|
||||||
|
|
||||||
time.Sleep(1 * time.Second)
|
|
||||||
|
|
||||||
defer v.Stop()
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user