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 BootTimeout
) )
// Suffrage is the type of suffrage -- voting or non-voting -- a node has.
type Suffrage int type Suffrage int
const ( const (
@ -42,6 +43,31 @@ const (
NonVoter 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 ( const (
requestTimeout = 5 * time.Second requestTimeout = 5 * time.Second
numJoinAttempts = 1 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 // Try an explicit join first. Joining an existing cluster is always given priority
// over trying to form a new cluster. // 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.logger.Printf("succeeded directly joining cluster via node at %s", j)
b.setBootStatus(BootJoin) b.setBootStatus(BootJoin)
return nil 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, // Do makes the actual join request. If the join is successful with any address,
// that address is returned. Otherwise, an error is returned. // 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 == "" { if id == "" {
return "", ErrNodeIDRequired return "", ErrNodeIDRequired
} }
@ -56,7 +56,7 @@ func (j *Joiner) Do(targetAddrs []string, id, addr string, voter bool) (string,
var joinee string var joinee string
for i := 0; i < j.numAttempts; i++ { for i := 0; i < j.numAttempts; i++ {
for _, ta := range targetAddrs { for _, ta := range targetAddrs {
joinee, err = j.join(ta, id, addr, voter) joinee, err = j.join(ta, id, addr, suf)
if err == nil { if err == nil {
// Success! // Success!
return joinee, nil return joinee, nil
@ -73,11 +73,11 @@ func (j *Joiner) Do(targetAddrs []string, id, addr string, voter bool) (string,
return "", ErrJoinFailed 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{ req := &command.JoinRequest{
Id: id, Id: id,
Address: addr, Address: addr,
Voter: voter, Voter: suf.IsVoter(),
} }
// Attempt to join. // Attempt to join.

@ -49,7 +49,7 @@ func Test_SingleJoinOK(t *testing.T) {
c := NewClient(&simpleDialer{}, 0) c := NewClient(&simpleDialer{}, 0)
joiner := NewJoiner(c, numAttempts, attemptInterval) 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 { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -68,7 +68,7 @@ func Test_SingleJoinZeroAttempts(t *testing.T) {
c := NewClient(&simpleDialer{}, 0) c := NewClient(&simpleDialer{}, 0)
joiner := NewJoiner(c, 0, attemptInterval) 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 { if err != ErrJoinFailed {
t.Fatalf("Incorrect error returned when zero attempts specified") t.Fatalf("Incorrect error returned when zero attempts specified")
} }
@ -99,7 +99,7 @@ func Test_SingleJoinFail(t *testing.T) {
c := NewClient(&simpleDialer{}, 0) c := NewClient(&simpleDialer{}, 0)
joiner := NewJoiner(c, numAttempts, attemptInterval) 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 { if err == nil {
t.Fatalf("expected error when joining bad node") t.Fatalf("expected error when joining bad node")
} }
@ -153,7 +153,7 @@ func Test_DoubleJoinOKSecondNode(t *testing.T) {
c := NewClient(&simpleDialer{}, 0) c := NewClient(&simpleDialer{}, 0)
joiner := NewJoiner(c, numAttempts, attemptInterval) 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 { if err != nil {
t.Fatal(err) 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)) joiner.SetCredentials(cluster.CredentialsFor(credStr, cfg.JoinAs))
if joins != nil && cfg.BootstrapExpect == 0 { if joins != nil && cfg.BootstrapExpect == 0 {
// Explicit join operation requested, so do it. // 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 { if err != nil {
return fmt.Errorf("failed to join cluster: %s", err.Error()) 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 { } else {
for { for {
log.Printf("discovery service returned %s as join address", addr) 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()) log.Printf("failed to join cluster at %s: %s", addr, err.Error())
time.Sleep(time.Second) time.Sleep(time.Second)

@ -222,14 +222,14 @@ func (n *Node) EnableTLSClient() {
// Join instructs this node to join the leader. // Join instructs this node to join the leader.
func (n *Node) Join(leader *Node) error { func (n *Node) Join(leader *Node) error {
joiner := cluster.NewJoiner(n.Client, 3, 1*time.Second) 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 return err
} }
// JoinAsNonVoter instructs this node to join the leader, but as a non-voting node. // JoinAsNonVoter instructs this node to join the leader, but as a non-voting node.
func (n *Node) JoinAsNonVoter(leader *Node) error { func (n *Node) JoinAsNonVoter(leader *Node) error {
joiner := cluster.NewJoiner(n.Client, 3, 1*time.Second) 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 return err
} }

Loading…
Cancel
Save