|
|
|
@ -977,6 +977,22 @@ func (s *Server) Shutdown() error {
|
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (s *Server) attemptLeadershipTransfer() (success bool) { |
|
|
|
|
leadershipTransferVersion := version.Must(version.NewVersion(LeaderTransferMinVersion)) |
|
|
|
|
|
|
|
|
|
ok, _ := ServersInDCMeetMinimumVersion(s, s.config.Datacenter, leadershipTransferVersion) |
|
|
|
|
if !ok { |
|
|
|
|
return false |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
future := s.raft.LeadershipTransfer() |
|
|
|
|
if err := future.Error(); err != nil { |
|
|
|
|
s.logger.Error("failed to transfer leadership, removing the server", "error", err) |
|
|
|
|
return false |
|
|
|
|
} |
|
|
|
|
return true |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Leave is used to prepare for a graceful shutdown of the server
|
|
|
|
|
func (s *Server) Leave() error { |
|
|
|
|
s.logger.Info("server starting leave") |
|
|
|
@ -996,24 +1012,9 @@ func (s *Server) Leave() error {
|
|
|
|
|
// removed for some reasonable period of time.
|
|
|
|
|
isLeader := s.IsLeader() |
|
|
|
|
if isLeader && numPeers > 1 { |
|
|
|
|
leadershipTransferVersion := version.Must(version.NewVersion(LeaderTransferMinVersion)) |
|
|
|
|
removeServer := false |
|
|
|
|
if ok, _ := ServersInDCMeetMinimumVersion(s, s.config.Datacenter, leadershipTransferVersion); !ok { |
|
|
|
|
// Transfer leadership to another node then leave the cluster
|
|
|
|
|
future := s.raft.LeadershipTransfer() |
|
|
|
|
if err := future.Error(); err != nil { |
|
|
|
|
s.logger.Error("failed to transfer leadership, removing the server", "error", err) |
|
|
|
|
// leadership transfer failed, fallback to removing the server from raft
|
|
|
|
|
removeServer = true |
|
|
|
|
} else { |
|
|
|
|
// we are not leader anymore, continue the flow to leave as follower
|
|
|
|
|
isLeader = false |
|
|
|
|
} |
|
|
|
|
if s.attemptLeadershipTransfer() { |
|
|
|
|
isLeader = false |
|
|
|
|
} else { |
|
|
|
|
// Leadership transfer is not available in the current version, fallback to removing the server from raft
|
|
|
|
|
removeServer = true |
|
|
|
|
} |
|
|
|
|
if removeServer { |
|
|
|
|
future := s.raft.RemoveServer(raft.ServerID(s.config.NodeID), 0, 0) |
|
|
|
|
if err := future.Error(); err != nil { |
|
|
|
|
s.logger.Error("failed to remove ourself as raft peer", "error", err) |
|
|
|
|