package themis import ( "context" "fmt" "time" "github.com/rs/zerolog/log" ) var loc *time.Location func init() { loc, _ = time.LoadLocation("America/New_York") } type Notifier struct { c chan struct{} } func NewNotifier(c chan struct{}) *Notifier { return &Notifier{ c: c, } } func (n *Notifier) Start(ctx context.Context) { m := NextMonday() sat := m.AddDate(0, 0, -2) if sat.Before(time.Now()) { sat = sat.AddDate(0, 0, 7) } t, err := time.ParseInLocation(time.DateTime, fmt.Sprintf("%s 17:00:00", sat.Format(time.DateOnly)), loc) if err != nil { panic("failed to parse next monday notif time. this is likely a bug.") } log.Debug().Time("next", t).Msg("starting notifier instance") first := time.NewTimer(time.Until(t)) <-first.C select { case <-ctx.Done(): log.Debug().Msg("context deadline exceeded, exiting notifier") return default: log.Debug().Msg("notifier tick") n.c <- struct{}{} } ticker := time.NewTicker(time.Hour * 24 * 7) for { select { case <-ctx.Done(): log.Debug().Msg("context deadline exceeded, exiting notifier") return case <-ticker.C: log.Debug().Msg("notifier tick") n.c <- struct{}{} } time.Sleep(time.Second) } } // Trigger the notifier manually. Should be used for testing purposes only. func (n *Notifier) Send() { n.c <- struct{}{} } func (n *Notifier) NotifyFunc(ctx context.Context, f func()) { for { select { case <-ctx.Done(): log.Debug().Msg("context deadline exceeded, exiting notify func") return case <-n.c: log.Debug().Msg("tick received, notifying function") f() } time.Sleep(time.Second) } }