82 lines
1.4 KiB
Go
82 lines
1.4 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 {
|
||
|
err := sendMessage(node, authCode, "heartbeat", authCode)
|
||
|
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 {
|
||
|
err := sendMessage(node, authCode, "election", authCode)
|
||
|
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
|
||
|
}
|
||
|
}
|