//go:generate mockgen -source=worker.go -destination=mocks/worker_mock.go -package=mocks package server import ( "time" "git.ctrlz.es/mgdelacroix/birthdaybot/model" "github.com/charmbracelet/log" ) type Worker interface { Start() Stop() } type SimpleWorker struct { server *Server logger *log.Logger stop chan bool stopped chan bool } func NewSimpleWorker(server *Server) *SimpleWorker { return &SimpleWorker{ server: server, logger: server.Logger, stop: make(chan bool, 1), stopped: make(chan bool, 1), } } func (w *SimpleWorker) Start() { w.logger.Info("starting worker") go w.run() w.logger.Info("worker started") } func (w *SimpleWorker) Stop() { w.logger.Info("stopping worker") w.stop <- true <-w.stopped w.logger.Info("worker stopped") } func (w *SimpleWorker) notifyDay(year, month, day int) { birthdays := model.FilterByDate(w.server.Birthdays(), year, month, day) w.logger.Info("notifying for date", "birthdays", len(birthdays), "year", year, "month", month, "day", day) for _, b := range birthdays { w.logger.Info("notifying for birthday", "name", b.Name) w.server.Notify(b) } } func (w *SimpleWorker) run() { // first we calculate the delta with 23:00 now := time.Now() eleven := time.Date(now.Year(), now.Month(), now.Day(), 23, 0, 0, 0, now.Location()) if eleven.Before(now) { // tomorrow at 23:00 eleven = time.Date(now.Year(), now.Month(), now.Day()+1, 23, 0, 0, 0, now.Location()) } firstTick := eleven.Sub(now) var ticker *time.Ticker w.logger.Info("first timer tick set", "tick", firstTick) select { case <-time.After(firstTick): ticker = time.NewTicker(24 * time.Hour) w.notifyDay(eleven.Year(), int(eleven.Month()), eleven.Day()) case <-w.stop: w.logger.Info("received stop signal") w.stopped <- true return } for { select { case t := <-ticker.C: w.logger.Info("ticker ticked for worker", "tick", t) w.notifyDay(t.Year(), int(t.Month()), t.Day()) case <-w.stop: w.logger.Info("received stop signal") w.stopped <- true return } } }