birthdaybot/server/worker.go

91 lines
2 KiB
Go
Raw Normal View History

2023-07-10 12:43:59 +01:00
//go:generate mockgen -source=worker.go -destination=mocks/worker_mock.go -package=mocks
2023-07-01 16:23:19 +01:00
package server
import (
"time"
"git.ctrlz.es/mgdelacroix/birthdaybot/model"
2023-07-01 16:23:19 +01:00
"github.com/charmbracelet/log"
)
type Worker interface {
Start()
Stop()
}
type SimpleWorker struct {
server *Server
2023-07-01 16:23:19 +01:00
logger *log.Logger
stop chan bool
stopped chan bool
}
func NewSimpleWorker(server *Server) *SimpleWorker {
return &SimpleWorker{
server: server,
logger: server.Logger,
2023-07-01 16:23:19 +01:00
stop: make(chan bool, 1),
stopped: make(chan bool, 1),
}
}
func (w *SimpleWorker) Start() {
2023-07-10 18:58:55 +01:00
w.logger.Debug("starting worker")
2023-07-01 16:23:19 +01:00
go w.run()
2023-07-10 18:58:55 +01:00
w.logger.Debug("worker started")
2023-07-01 16:23:19 +01:00
}
func (w *SimpleWorker) Stop() {
2023-07-10 18:58:55 +01:00
w.logger.Debug("stopping worker")
2023-07-01 16:23:19 +01:00
w.stop <- true
<-w.stopped
2023-07-10 18:58:55 +01:00
w.logger.Debug("worker stopped")
2023-07-01 16:23:19 +01:00
}
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
2023-07-10 18:58:55 +01:00
w.logger.Debug("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:
2023-07-10 18:58:55 +01:00
w.logger.Debug("received stop signal")
w.stopped <- true
return
}
2023-07-01 16:23:19 +01:00
for {
select {
case t := <-ticker.C:
2023-07-10 18:58:55 +01:00
w.logger.Debug("ticker ticked for worker", "tick", t)
w.notifyDay(t.Year(), int(t.Month()), t.Day())
2023-07-01 16:23:19 +01:00
case <-w.stop:
2023-07-10 18:58:55 +01:00
w.logger.Debug("received stop signal")
2023-07-01 16:23:19 +01:00
w.stopped <- true
return
}
}
}