1
0
Fork 0

Use new types with Joiner

master
Philip O'Toole 9 months ago
parent 69ff3573af
commit c8edfa93dc

@ -35,6 +35,7 @@ const (
BootTimeout
)
// Suffrage is the type of suffrage -- voting or non-voting -- a node has.
type Suffrage int
const (
@ -42,6 +43,31 @@ const (
NonVoter
)
// VoterSuffrage returns a Suffrage based on the given boolean.
func VoterSuffrage(b bool) Suffrage {
if b {
return Voter
}
return NonVoter
}
// String returns a string representation of the Suffrage.
func (s Suffrage) String() string {
switch s {
case Voter:
return "voter"
case NonVoter:
return "non-voter"
default:
panic("unknown suffrage")
}
}
// IsVoter returns whether the Suffrage is a Voter.
func (s Suffrage) IsVoter() bool {
return s == Voter
}
const (
requestTimeout = 5 * time.Second
numJoinAttempts = 1
@ -146,7 +172,7 @@ func (b *Bootstrapper) Boot(id, raftAddr string, suf Suffrage, done func() bool,
// Try an explicit join first. Joining an existing cluster is always given priority
// over trying to form a new cluster.
if j, err := joiner.Do(targets, id, raftAddr, true); err == nil {
if j, err := joiner.Do(targets, id, raftAddr, suf); err == nil {
b.logger.Printf("succeeded directly joining cluster via node at %s", j)
b.setBootStatus(BootJoin)
return nil

@ -47,7 +47,7 @@ func (j *Joiner) SetCredentials(creds *Credentials) {
// Do makes the actual join request. If the join is successful with any address,
// that address is returned. Otherwise, an error is returned.
func (j *Joiner) Do(targetAddrs []string, id, addr string, voter bool) (string, error) {
func (j *Joiner) Do(targetAddrs []string, id, addr string, suf Suffrage) (string, error) {
if id == "" {
return "", ErrNodeIDRequired
}
@ -56,7 +56,7 @@ func (j *Joiner) Do(targetAddrs []string, id, addr string, voter bool) (string,
var joinee string
for i := 0; i < j.numAttempts; i++ {
for _, ta := range targetAddrs {
joinee, err = j.join(ta, id, addr, voter)
joinee, err = j.join(ta, id, addr, suf)
if err == nil {
// Success!
return joinee, nil
@ -73,11 +73,11 @@ func (j *Joiner) Do(targetAddrs []string, id, addr string, voter bool) (string,
return "", ErrJoinFailed
}
func (j *Joiner) join(targetAddr, id, addr string, voter bool) (string, error) {
func (j *Joiner) join(targetAddr, id, addr string, suf Suffrage) (string, error) {
req := &command.JoinRequest{
Id: id,
Address: addr,
Voter: voter,
Voter: suf.IsVoter(),
}
// Attempt to join.

@ -49,7 +49,7 @@ func Test_SingleJoinOK(t *testing.T) {
c := NewClient(&simpleDialer{}, 0)
joiner := NewJoiner(c, numAttempts, attemptInterval)
addr, err := joiner.Do([]string{srv.Addr()}, "id0", "1.2.3.4", true)
addr, err := joiner.Do([]string{srv.Addr()}, "id0", "1.2.3.4", Voter)
if err != nil {
t.Fatal(err)
}
@ -68,7 +68,7 @@ func Test_SingleJoinZeroAttempts(t *testing.T) {
c := NewClient(&simpleDialer{}, 0)
joiner := NewJoiner(c, 0, attemptInterval)
_, err := joiner.Do([]string{srv.Addr()}, "id0", "1.2.3.4", true)
_, err := joiner.Do([]string{srv.Addr()}, "id0", "1.2.3.4", Voter)
if err != ErrJoinFailed {
t.Fatalf("Incorrect error returned when zero attempts specified")
}
@ -99,7 +99,7 @@ func Test_SingleJoinFail(t *testing.T) {
c := NewClient(&simpleDialer{}, 0)
joiner := NewJoiner(c, numAttempts, attemptInterval)
_, err := joiner.Do([]string{srv.Addr()}, "id0", "1.2.3.4", true)
_, err := joiner.Do([]string{srv.Addr()}, "id0", "1.2.3.4", Voter)
if err == nil {
t.Fatalf("expected error when joining bad node")
}
@ -153,7 +153,7 @@ func Test_DoubleJoinOKSecondNode(t *testing.T) {
c := NewClient(&simpleDialer{}, 0)
joiner := NewJoiner(c, numAttempts, attemptInterval)
addr, err := joiner.Do([]string{srv1.Addr(), srv2.Addr()}, "id0", "1.2.3.4", true)
addr, err := joiner.Do([]string{srv1.Addr(), srv2.Addr()}, "id0", "1.2.3.4", Voter)
if err != nil {
t.Fatal(err)
}

@ -447,7 +447,7 @@ func createCluster(cfg *Config, hasPeers bool, client *cluster.Client, str *stor
joiner.SetCredentials(cluster.CredentialsFor(credStr, cfg.JoinAs))
if joins != nil && cfg.BootstrapExpect == 0 {
// Explicit join operation requested, so do it.
j, err := joiner.Do(joins, str.ID(), cfg.RaftAdv, !cfg.RaftNonVoter)
j, err := joiner.Do(joins, str.ID(), cfg.RaftAdv, cluster.VoterSuffrage(!cfg.RaftNonVoter))
if err != nil {
return fmt.Errorf("failed to join cluster: %s", err.Error())
}
@ -534,7 +534,7 @@ func createCluster(cfg *Config, hasPeers bool, client *cluster.Client, str *stor
} else {
for {
log.Printf("discovery service returned %s as join address", addr)
if j, err := joiner.Do([]string{addr}, str.ID(), cfg.RaftAdv, !cfg.RaftNonVoter); err != nil {
if j, err := joiner.Do([]string{addr}, str.ID(), cfg.RaftAdv, cluster.VoterSuffrage(!cfg.RaftNonVoter)); err != nil {
log.Printf("failed to join cluster at %s: %s", addr, err.Error())
time.Sleep(time.Second)

@ -222,14 +222,14 @@ func (n *Node) EnableTLSClient() {
// Join instructs this node to join the leader.
func (n *Node) Join(leader *Node) error {
joiner := cluster.NewJoiner(n.Client, 3, 1*time.Second)
_, err := joiner.Do([]string{leader.RaftAddr}, n.Store.ID(), n.RaftAddr, true)
_, err := joiner.Do([]string{leader.RaftAddr}, n.Store.ID(), n.RaftAddr, cluster.Voter)
return err
}
// JoinAsNonVoter instructs this node to join the leader, but as a non-voting node.
func (n *Node) JoinAsNonVoter(leader *Node) error {
joiner := cluster.NewJoiner(n.Client, 3, 1*time.Second)
_, err := joiner.Do([]string{leader.RaftAddr}, n.Store.ID(), n.RaftAddr, false)
_, err := joiner.Do([]string{leader.RaftAddr}, n.Store.ID(), n.RaftAddr, cluster.NonVoter)
return err
}

Loading…
Cancel
Save