Files
silo-server/internal/taskmanager/triggers/startup.go
T

89 lines
1.6 KiB
Go

package triggers
import (
"sync"
"time"
"github.com/Silo-Server/silo-server/internal/taskmanager"
)
const startupDelay = 5 * time.Second
// StartupTrigger fires once, shortly after Start() is called. Subsequent
// calls to Start() (e.g. re-arming after execution) are no-ops.
type StartupTrigger struct {
cfg taskmanager.TriggerConfig
ch chan struct{}
nextRun time.Time
timer *time.Timer
stopCh chan struct{}
fired bool
mu sync.Mutex
}
func NewStartupTrigger(cfg taskmanager.TriggerConfig) *StartupTrigger {
return &StartupTrigger{
cfg: cfg,
ch: make(chan struct{}, 1),
}
}
func (s *StartupTrigger) Start(_ *taskmanager.ExecutionResult) {
s.mu.Lock()
defer s.mu.Unlock()
// Drain any stale signal from a previous timer fire.
select {
case <-s.ch:
default:
}
if s.fired {
return
}
s.fired = true
s.stopCh = make(chan struct{})
s.nextRun = time.Now().Add(startupDelay)
s.timer = time.NewTimer(startupDelay)
go func() {
select {
case <-s.stopCh:
if !s.timer.Stop() {
select {
case <-s.timer.C:
default:
}
}
return
case <-s.timer.C:
select {
case s.ch <- struct{}{}:
default:
}
}
}()
}
func (s *StartupTrigger) Stop() {
s.mu.Lock()
defer s.mu.Unlock()
if s.stopCh != nil {
select {
case <-s.stopCh:
default:
close(s.stopCh)
}
}
}
func (s *StartupTrigger) NextRunTime() time.Time {
s.mu.Lock()
defer s.mu.Unlock()
return s.nextRun
}
func (s *StartupTrigger) Config() taskmanager.TriggerConfig { return s.cfg }
func (s *StartupTrigger) C() <-chan struct{} { return s.ch }