package main import ( "fmt" "log/slog" "time" "github.com/google/uuid" "go-mod.ewintr.nl/planner/item" ) type Recur struct { repoSync Syncer repoRecur Recurrer logger *slog.Logger } func NewRecur(repoRecur Recurrer, repoSync Syncer, logger *slog.Logger) *Recur { r := &Recur{ repoRecur: repoRecur, repoSync: repoSync, logger: logger, } return r } func (r *Recur) Run(interval time.Duration) { ticker := time.NewTicker(interval) for range ticker.C { if err := r.Recur(); err != nil { r.logger.Error("could not recur", "error", err) } } } func (r *Recur) Recur() error { r.logger.Info("start looking for recurring items") items, err := r.repoRecur.RecursBefore(time.Now()) if err != nil { return err } r.logger.Info("found recurring items", "count", len(items)) for _, i := range items { r.logger.Info("processing recurring item", "item", fmt.Sprintf("%+v", i)) // spawn instance ne, err := item.NewEvent(i) if err != nil { return err } r.logger.Info("processing recurring event", "event", fmt.Sprintf("%+v", ne)) y, m, d := i.RecurNext.Date() ne.ID = uuid.New().String() ne.Recurrer = nil ne.RecurNext = time.Time{} ne.Start = time.Date(y, m, d, ne.Start.Hour(), ne.Start.Minute(), 0, 0, time.UTC) r.logger.Info("created instance of recurring event", "event", fmt.Sprintf("%+v", ne)) ni, err := ne.Item() if err != nil { return err } if err := r.repoSync.Update(ni, time.Now()); err != nil { return err } r.logger.Info("storen instance of recurring event", "recEventID", ne.ID, "instanceID", ni.ID) // set next next := i.Recurrer.NextAfter(i.RecurNext) if err := r.repoRecur.RecursNext(i.ID, next, time.Now()); err != nil { return err } r.logger.Info("updated recur date", "recEventID", ne.ID, "next", next) } r.logger.Info("processed recurring items", "count", len(items)) return nil }