func (se *ScheduledElector) PrometheusLivenessCheck(lastRequestUnixNano int64, timeout time.Duration) {
	elapsed := time.Since(time.Unix(0, lastRequestUnixNano))
	leader, err := se.IsLeader()
	if err != nil {
		log.Error("msg", err.Error())
	}
	if leader {
		if elapsed > timeout {
			log.Warn("msg", "Prometheus timeout exceeded", "timeout", timeout, "elapsed", elapsed)
			se.pauseScheduledElection()
			log.Warn("msg", "Scheduled election is paused. Instance is removed from election pool.")
			err := se.Resign()
			if err != nil {
				log.Error("msg", err.Error())
			}
		}
	} else {
		if se.isScheduledElectionPaused() && elapsed < timeout {
			log.Info("msg", "Prometheus seems alive. Resuming scheduled election.")
			se.resumeScheduledElection()
		}
	}
}
PrometheusLivenessCheck checks if the last request seen from prometheus and if it's older than a
timeout, and if so, give up leadership.
package util
import (
	"sync"
	"time"
	"github.com/timescale/promscale/pkg/log"
)
type Election interface {
	ID() string
	BecomeLeader() (bool, error)
	IsLeader() (bool, error)
	Resign() error
}
type Elector struct {
	election Election
}
func NewElector(election Election) *Elector {
	elector := &Elector{election: election}
	return elector
}
func (e *Elector) ID() string {
	return e.election.ID()
}
func (e *Elector) BecomeLeader() (bool, error) {
	leader, err := e.election.BecomeLeader()
	if err != nil {
		log.Error("msg", "Error while trying to become a leader", "err", err)
	}
	if leader {
		log.Info("msg", "Instance became a leader", "groupID", e.ID())
	}
	return leader, err
}
func (e *Elector) IsLeader() (bool, error) {
	return e.election.IsLeader()
}
func (e *Elector) Resign() error {
	err := e.election.Resign()
	if err != nil {
		log.Error("err", "Failed to resign", "err", err)
	} else {
		log.Info("msg", "Instance is no longer a leader")
	}
	return err
}
type ScheduledElector struct {
	Elector
	ticker                  *time.Ticker
	lock                    sync.RWMutex
	pausedScheduledElection bool
}
func NewScheduledElector(election Election, electionInterval time.Duration) *ScheduledElector {
	scheduledElector := &ScheduledElector{Elector: Elector{election}, ticker: time.NewTicker(electionInterval)}
	leader := scheduledElector.elect()
	if leader {
		log.Info("msg", "leader election started: acting as leader")
	} else {
		log.Info("msg", "leader election started: acting as follower (will not write until I become leader)")
	}
	go scheduledElector.scheduledElection()
	return scheduledElector
}
func (se *ScheduledElector) pauseScheduledElection() {
	se.lock.Lock()
	defer se.lock.Unlock()
	se.pausedScheduledElection = true
}
func (se *ScheduledElector) resumeScheduledElection() {
	se.lock.Lock()
	defer se.lock.Unlock()
	se.pausedScheduledElection = false
}
func (se *ScheduledElector) isScheduledElectionPaused() bool {
	se.lock.RLock()
	defer se.lock.RUnlock()
	return se.pausedScheduledElection
}