blob: 973865e43531f6a6b5a56cd8ad0526f587583aee [file] [log] [blame]
package common
import (
"github.com/sirupsen/logrus"
"sync"
"time"
)
/*
IntervalHandler is used to run a routine at regular intervals and provide all the necessary
utilities to manage the execution.
*/
type IntervalHandler struct {
// Interval period in between each execution (in seconds?)
Interval int
// function to execute after each interval
function func()
// Channel listening to execution events
execute chan _ExecutionState
// Channel listening for a termination event
terminate chan struct{}
// Current execution state of the handler
state _ExecutionState
wg sync.WaitGroup
}
// Define execution state constants
type _ExecutionState uint8
const (
STARTED _ExecutionState = iota
STOPPED
PAUSED
RESUMED
)
// Execute state string equivalents
var _ExecutionStateEnum = []string{
"STARTED",
"STOPPED",
"PAUSED",
"RESUMED",
}
func (s _ExecutionState) String() string {
return _ExecutionStateEnum[s]
}
/*
NewIntervalHandler instantiates a new interval based function execution handler
*/
func NewIntervalHandler(interval int, function func()) *IntervalHandler {
handler := &IntervalHandler{
Interval: interval,
function: function,
}
handler.execute = make(chan _ExecutionState)
handler.terminate = make(chan struct{})
handler.state = STOPPED
return handler
}
/*
_Execute is a routine running concurrently and listening to execution events
*/
func (h *IntervalHandler) _Execute() {
defer h.wg.Done()
for {
select {
case h.state = <-h.execute:
Logger().WithFields(logrus.Fields{
"handler": h,
}).Debug("Processing execution state")
switch h.state {
case STARTED:
case PAUSED:
case RESUMED:
h.state = STARTED
case STOPPED:
fallthrough
default:
h.terminate <- struct{}{}
}
case <-h.terminate:
return
default:
if h.state == STARTED {
h.function()
time.Sleep(time.Duration(h.Interval) * time.Second)
} else {
// TODO: replace hardcoded delay with a configurable parameter
time.Sleep(1 * time.Second)
}
}
}
}
/*
Start initiates the interval based function execution
*/
func (h *IntervalHandler) Start() {
Logger().WithFields(logrus.Fields{
"handler": h,
}).Info("Starting interval handler")
if h.execute == nil {
return
}
if h.state == STOPPED {
go h._Execute()
h.execute <- STARTED
}
}
/*
Pause interrupts the interval based function execution
*/
func (h *IntervalHandler) Pause() {
Logger().WithFields(logrus.Fields{
"handler": h,
}).Info("Pausing interval handler")
if h.execute == nil || h.state == STOPPED {
return
}
if h.state == STARTED {
h.execute <- PAUSED
}
}
/*
Resume continues the interval based function execution
*/
func (h *IntervalHandler) Resume() {
Logger().WithFields(logrus.Fields{
"handler": h,
}).Info("Resuming interval handler")
if h.execute == nil || h.state == STOPPED {
return
}
if h.state == PAUSED {
h.execute <- RESUMED
}
}
/*
Stop terminates the interval based function execution
*/
func (h *IntervalHandler) Stop() {
Logger().WithFields(logrus.Fields{
"handler": h,
}).Info("Stopping interval handler")
if h.execute == nil || h.state == STOPPED {
return
}
h.execute <- STOPPED
}