Add cron schedules and sync docs
This commit is contained in:
@@ -11,6 +11,8 @@ import (
|
||||
"github.com/monlet/agent/internal/runner"
|
||||
)
|
||||
|
||||
var parseCronSchedule = config.ParseCronSchedule
|
||||
|
||||
// Event is a contract-shaped check result emitted by the scheduler.
|
||||
type Event struct {
|
||||
EventID string `json:"event_id"`
|
||||
@@ -207,8 +209,10 @@ func (w *checkWorker) loop(initial config.CheckConfig) {
|
||||
w.wg.Done()
|
||||
}()
|
||||
cfg := initial
|
||||
t := time.NewTicker(cfg.Interval.Duration)
|
||||
t := time.NewTimer(time.Hour)
|
||||
stopTimer(t)
|
||||
defer t.Stop()
|
||||
var timerCh <-chan time.Time
|
||||
|
||||
running := false
|
||||
stopping := false
|
||||
@@ -230,7 +234,26 @@ func (w *checkWorker) loop(initial config.CheckConfig) {
|
||||
}()
|
||||
}
|
||||
|
||||
start(cfg)
|
||||
arm := func(c config.CheckConfig, immediateInterval bool) bool {
|
||||
delay, err := nextDelay(c, time.Now(), immediateInterval)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
resetTimer(t, delay)
|
||||
timerCh = t.C
|
||||
return true
|
||||
}
|
||||
disarm := func() {
|
||||
stopTimer(t)
|
||||
timerCh = nil
|
||||
}
|
||||
|
||||
if !arm(cfg, true) {
|
||||
if w.hooks.OnStopped != nil {
|
||||
w.hooks.OnStopped(cfg.ID)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
@@ -257,11 +280,21 @@ func (w *checkWorker) loop(initial config.CheckConfig) {
|
||||
continue
|
||||
}
|
||||
cfg = next
|
||||
t.Reset(cfg.Interval.Duration)
|
||||
if cfg.UsesCron() {
|
||||
runAfterCurrent = false
|
||||
if !arm(cfg, false) {
|
||||
return
|
||||
}
|
||||
continue
|
||||
}
|
||||
if running {
|
||||
runAfterCurrent = true
|
||||
disarm()
|
||||
} else {
|
||||
start(cfg)
|
||||
if !arm(cfg, false) {
|
||||
return
|
||||
}
|
||||
}
|
||||
case <-w.doneCh:
|
||||
running = false
|
||||
@@ -281,26 +314,35 @@ func (w *checkWorker) loop(initial config.CheckConfig) {
|
||||
}
|
||||
if runAfterCurrent {
|
||||
runAfterCurrent = false
|
||||
startAfterDrain := true
|
||||
for {
|
||||
select {
|
||||
case next := <-w.updateCh:
|
||||
if !reflect.DeepEqual(cfg, next) {
|
||||
cfg = next
|
||||
t.Reset(cfg.Interval.Duration)
|
||||
startAfterDrain = !cfg.UsesCron()
|
||||
}
|
||||
default:
|
||||
start(cfg)
|
||||
if startAfterDrain {
|
||||
start(cfg)
|
||||
}
|
||||
if !arm(cfg, false) {
|
||||
return
|
||||
}
|
||||
goto nextLoop
|
||||
}
|
||||
}
|
||||
nextLoop:
|
||||
continue
|
||||
}
|
||||
case <-t.C:
|
||||
case <-timerCh:
|
||||
if stopping {
|
||||
continue
|
||||
}
|
||||
start(cfg)
|
||||
if !arm(cfg, false) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -358,3 +400,41 @@ func incidentKey(agentID string, c config.CheckConfig) string {
|
||||
}
|
||||
return agentID + ":" + c.ID
|
||||
}
|
||||
|
||||
func nextDelay(c config.CheckConfig, now time.Time, immediateInterval bool) (time.Duration, error) {
|
||||
if c.UsesCron() {
|
||||
schedule, err := parseCronSchedule(c.Cron)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return delayUntil(now, schedule.Next(now)), nil
|
||||
}
|
||||
if immediateInterval {
|
||||
return 0, nil
|
||||
}
|
||||
return c.Interval.Duration, nil
|
||||
}
|
||||
|
||||
func delayUntil(now, next time.Time) time.Duration {
|
||||
if next.Before(now) {
|
||||
return 0
|
||||
}
|
||||
return next.Sub(now)
|
||||
}
|
||||
|
||||
func resetTimer(t *time.Timer, d time.Duration) {
|
||||
if d < 0 {
|
||||
d = 0
|
||||
}
|
||||
stopTimer(t)
|
||||
t.Reset(d)
|
||||
}
|
||||
|
||||
func stopTimer(t *time.Timer) {
|
||||
if !t.Stop() {
|
||||
select {
|
||||
case <-t.C:
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user