91 lines
1.5 KiB
Go
91 lines
1.5 KiB
Go
package main
|
|
|
|
import (
|
|
"log"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
var (
|
|
isMaster bool
|
|
masterNode string
|
|
masterNodeMux sync.RWMutex
|
|
)
|
|
|
|
const (
|
|
heartbeatInterval = 5 * time.Second
|
|
heartbeatTimeout = 15 * time.Second
|
|
electionTimeout = 10 * time.Second
|
|
)
|
|
|
|
func sendHeartbeats() {
|
|
for {
|
|
if !isMaster {
|
|
return
|
|
}
|
|
for _, node := range peers {
|
|
msg := Message{
|
|
ID: hostID,
|
|
Type: "heartbeat",
|
|
Content: authCode,
|
|
}
|
|
err := sendMessage(node, msg)
|
|
if err != nil {
|
|
log.Printf("Error sending heartbeat to %s: %v", node, err)
|
|
}
|
|
}
|
|
time.Sleep(heartbeatInterval)
|
|
}
|
|
}
|
|
|
|
func checkMasterHeartbeat() {
|
|
for {
|
|
time.Sleep(heartbeatTimeout)
|
|
masterNodeMux.RLock()
|
|
if masterNode == authCode || masterNode == "" {
|
|
masterNodeMux.RUnlock()
|
|
continue
|
|
}
|
|
masterNodeMux.RUnlock()
|
|
|
|
masterNodeMux.Lock()
|
|
masterNode = ""
|
|
masterNodeMux.Unlock()
|
|
startElection()
|
|
}
|
|
}
|
|
|
|
func startElection() {
|
|
masterNodeMux.Lock()
|
|
defer masterNodeMux.Unlock()
|
|
|
|
for _, node := range peers {
|
|
msg := Message{
|
|
ID: hostID,
|
|
Type: "election",
|
|
Content: authCode,
|
|
}
|
|
err := sendMessage(node, msg)
|
|
if err != nil {
|
|
log.Printf("Error sending election message to %s: %v", node, err)
|
|
}
|
|
}
|
|
|
|
isMaster = true
|
|
go sendHeartbeats()
|
|
}
|
|
|
|
func handleHeartbeat(content string) {
|
|
masterNodeMux.Lock()
|
|
defer masterNodeMux.Unlock()
|
|
masterNode = content
|
|
}
|
|
|
|
func handleElection(content string) {
|
|
masterNodeMux.Lock()
|
|
defer masterNodeMux.Unlock()
|
|
|
|
if content < authCode {
|
|
masterNode = content
|
|
}
|
|
}
|