74 lines
1.6 KiB
Go
74 lines
1.6 KiB
Go
package main
|
|
|
|
import (
|
|
log "github.com/AcalephStorage/consul-alerts/Godeps/_workspace/src/github.com/Sirupsen/logrus"
|
|
consulapi "github.com/AcalephStorage/consul-alerts/Godeps/_workspace/src/github.com/hashicorp/consul/api"
|
|
"time"
|
|
)
|
|
|
|
const LockKey = "consul-alerts/leader"
|
|
|
|
type LeaderElection struct {
|
|
lock *consulapi.Lock
|
|
cleanupChannel chan struct{}
|
|
stopChannel chan struct{}
|
|
leader bool
|
|
}
|
|
|
|
func (l *LeaderElection) start() {
|
|
clean := false
|
|
for !clean {
|
|
select {
|
|
case <-l.cleanupChannel:
|
|
clean = true
|
|
default:
|
|
log.Infoln("Running for leader election...")
|
|
intChan, _ := l.lock.Lock(l.stopChannel)
|
|
if intChan != nil {
|
|
log.Infoln("Now acting as leader.")
|
|
l.leader = true
|
|
<-intChan
|
|
l.leader = false
|
|
log.Infoln("Lost leadership.")
|
|
l.lock.Unlock()
|
|
l.lock.Destroy()
|
|
} else {
|
|
time.Sleep(10000 * time.Millisecond)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func (l *LeaderElection) stop() {
|
|
log.Infoln("cleaning up")
|
|
l.cleanupChannel <- struct{}{}
|
|
l.stopChannel <- struct{}{}
|
|
l.lock.Unlock()
|
|
l.lock.Destroy()
|
|
l.leader = false
|
|
log.Infoln("cleanup done")
|
|
}
|
|
|
|
func startLeaderElection(addr, dc, acl string) *LeaderElection {
|
|
config := consulapi.DefaultConfig()
|
|
config.Address = addr
|
|
config.Datacenter = dc
|
|
config.Token = acl
|
|
client, _ := consulapi.NewClient(config)
|
|
lock, _ := client.LockKey(LockKey)
|
|
|
|
leader := &LeaderElection{
|
|
lock: lock,
|
|
cleanupChannel: make(chan struct{}, 1),
|
|
stopChannel: make(chan struct{}, 1),
|
|
}
|
|
|
|
go leader.start()
|
|
|
|
return leader
|
|
}
|
|
|
|
func hasLeader() bool {
|
|
return consulClient.CheckKeyExists(LockKey)
|
|
}
|