1
0
Fork 0

Push in read-only status

Similar to DNS autoclustering, the Store doesn't know its intended
read-only state.
master
Philip O'Toole 9 months ago
parent f3b8f023dc
commit e700b03291

@ -322,7 +322,7 @@ func createDiscoService(cfg *Config, str *store.Store) (*disco.Service, error) {
return nil, fmt.Errorf("invalid disco service: %s", cfg.DiscoMode) return nil, fmt.Errorf("invalid disco service: %s", cfg.DiscoMode)
} }
return disco.NewService(c, str), nil return disco.NewService(c, str, disco.VoterSuffrage(!cfg.RaftNonVoter)), nil
} }
func startHTTPService(cfg *Config, str *store.Store, cltr *cluster.Client, credStr *auth.CredentialsStore) (*httpd.Service, error) { func startHTTPService(cfg *Config, str *store.Store, cltr *cluster.Client, credStr *auth.CredentialsStore) (*httpd.Service, error) {

@ -37,14 +37,33 @@ type Store interface {
// IsLeader returns whether this node is the Leader. // IsLeader returns whether this node is the Leader.
IsLeader() bool IsLeader() bool
// IsVoter returns whether this node is a voter. Only Voters can be Leaders.
IsVoter() (bool, error)
// RegisterLeaderChange registers a channel that will be notified when // RegisterLeaderChange registers a channel that will be notified when
// a leadership change occurs. // a leadership change occurs.
RegisterLeaderChange(c chan<- struct{}) RegisterLeaderChange(c chan<- struct{})
} }
// Suffrage is the type of suffrage -- voting or non-voting -- a node has.
type Suffrage int
const (
SuffrageUnknown Suffrage = iota
Voter
NonVoter
)
// VoterSuffrage returns a Suffrage based on the given boolean.
func VoterSuffrage(b bool) Suffrage {
if b {
return Voter
}
return NonVoter
}
// IsVoter returns whether the Suffrage indicates a Voter.
func (s Suffrage) IsVoter() bool {
return s == Voter
}
// Service represents a Discovery Service instance. // Service represents a Discovery Service instance.
type Service struct { type Service struct {
RegisterInterval time.Duration RegisterInterval time.Duration
@ -52,6 +71,7 @@ type Service struct {
c Client c Client
s Store s Store
suf Suffrage
logger *log.Logger logger *log.Logger
@ -60,11 +80,11 @@ type Service struct {
} }
// NewService returns an instantiated Discovery Service. // NewService returns an instantiated Discovery Service.
func NewService(c Client, s Store) *Service { func NewService(c Client, s Store, suf Suffrage) *Service {
return &Service{ return &Service{
c: c, c: c,
s: s, s: s,
suf: suf,
RegisterInterval: 3 * time.Second, RegisterInterval: 3 * time.Second,
ReportInterval: 10 * time.Second, ReportInterval: 10 * time.Second,
logger: log.New(os.Stderr, "[disco] ", log.LstdFlags), logger: log.New(os.Stderr, "[disco] ", log.LstdFlags),
@ -84,7 +104,7 @@ func (s *Service) Register(id, apiAddr, addr string) (bool, string, error) {
return false, cRaftAddr, nil return false, cRaftAddr, nil
} }
if s.isVoter() { if s.suf.IsVoter() {
ok, err = s.c.InitializeLeader(id, apiAddr, addr) ok, err = s.c.InitializeLeader(id, apiAddr, addr)
if err != nil { if err != nil {
s.logger.Printf("failed to initialize as Leader: %s", err.Error()) s.logger.Printf("failed to initialize as Leader: %s", err.Error())
@ -157,8 +177,3 @@ func (s *Service) updateContact(t time.Time) {
defer s.mu.Unlock() defer s.mu.Unlock()
s.lastContact = t s.lastContact = t
} }
func (s *Service) isVoter() bool {
v, _ := s.s.IsVoter()
return v
}

@ -7,7 +7,7 @@ import (
) )
func Test_NewServce(t *testing.T) { func Test_NewServce(t *testing.T) {
s := NewService(&mockClient{}, &mockStore{}) s := NewService(&mockClient{}, &mockStore{}, Voter)
if s == nil { if s == nil {
t.Fatalf("service is nil") t.Fatalf("service is nil")
} }
@ -24,7 +24,7 @@ func Test_RegisterGetLeaderOK(t *testing.T) {
} }
c := &mockStore{} c := &mockStore{}
s := NewService(m, c) s := NewService(m, c, Voter)
s.RegisterInterval = 10 * time.Millisecond s.RegisterInterval = 10 * time.Millisecond
ok, addr, err := s.Register("1", "localhost:4001", "localhost:4002") ok, addr, err := s.Register("1", "localhost:4001", "localhost:4002")
@ -52,7 +52,7 @@ func Test_RegisterInitializeLeader(t *testing.T) {
} }
c := &mockStore{} c := &mockStore{}
s := NewService(m, c) s := NewService(m, c, Voter)
s.RegisterInterval = 10 * time.Millisecond s.RegisterInterval = 10 * time.Millisecond
ok, addr, err := s.Register("1", "localhost:4001", "localhost:4002") ok, addr, err := s.Register("1", "localhost:4001", "localhost:4002")
@ -82,12 +82,8 @@ func Test_RegisterNonVoter(t *testing.T) {
return false, nil return false, nil
} }
c := &mockStore{ c := &mockStore{}
isVoterFn: func() (bool, error) { s := NewService(m, c, NonVoter)
return false, nil
},
}
s := NewService(m, c)
s.RegisterInterval = 10 * time.Millisecond s.RegisterInterval = 10 * time.Millisecond
ok, addr, err := s.Register("1", "localhost:4001", "localhost:4002") ok, addr, err := s.Register("1", "localhost:4001", "localhost:4002")
@ -120,7 +116,7 @@ func Test_StartReportingTimer(t *testing.T) {
return true return true
} }
s := NewService(m, c) s := NewService(m, c, Voter)
s.ReportInterval = 10 * time.Millisecond s.ReportInterval = 10 * time.Millisecond
go s.StartReporting("1", "localhost:4001", "localhost:4002") go s.StartReporting("1", "localhost:4001", "localhost:4002")
@ -147,7 +143,7 @@ func Test_StartReportingChange(t *testing.T) {
} }
wg.Add(1) wg.Add(1)
s := NewService(m, c) s := NewService(m, c, Voter)
s.ReportInterval = 10 * time.Minute // Nothing will happen due to timer. s.ReportInterval = 10 * time.Minute // Nothing will happen due to timer.
done := s.StartReporting("1", "localhost:4001", "localhost:4002") done := s.StartReporting("1", "localhost:4001", "localhost:4002")
@ -190,7 +186,6 @@ func (m *mockClient) String() string {
type mockStore struct { type mockStore struct {
isLeaderFn func() bool isLeaderFn func() bool
isVoterFn func() (bool, error)
registerLeaderChangeFn func(c chan<- struct{}) registerLeaderChangeFn func(c chan<- struct{})
} }
@ -201,13 +196,6 @@ func (m *mockStore) IsLeader() bool {
return false return false
} }
func (m *mockStore) IsVoter() (bool, error) {
if m.isVoterFn != nil {
return m.isVoterFn()
}
return true, nil
}
func (m *mockStore) RegisterLeaderChange(c chan<- struct{}) { func (m *mockStore) RegisterLeaderChange(c chan<- struct{}) {
if m.registerLeaderChangeFn != nil { if m.registerLeaderChangeFn != nil {
m.registerLeaderChangeFn(c) m.registerLeaderChangeFn(c)

Loading…
Cancel
Save