diff --git a/dist/plannersync b/dist/plannersync index 5b78bf7..64199cc 100755 Binary files a/dist/plannersync and b/dist/plannersync differ diff --git a/sync/service/recur.go b/sync/service/recur.go index e2ab466..65d1113 100644 --- a/sync/service/recur.go +++ b/sync/service/recur.go @@ -11,6 +11,7 @@ import ( type Recur struct { repoSync Syncer repoRecur Recurrer + days int logger *slog.Logger } @@ -24,37 +25,50 @@ func NewRecur(repoRecur Recurrer, repoSync Syncer, logger *slog.Logger) *Recur { return r } -func (r *Recur) Run(interval time.Duration) { +func (r *Recur) Run(days int, interval time.Duration) { + r.days = days ticker := time.NewTicker(interval) for range ticker.C { - if err := r.Recur(); err != nil { + today := item.NewDateFromString(time.Now().Format(item.DateFormat)) + last := today.Add(r.days) + if err := r.Recur(last); err != nil { r.logger.Error("could not recur", "error", err) } } } -func (r *Recur) Recur() error { - r.logger.Info("start looking for recurring items") - today := item.NewDateFromString(time.Now().Format(item.DateFormat)) - items, err := r.repoRecur.ShouldRecur(today) +func (r *Recur) Recur(until item.Date) error { + r.logger.Info("start looking for recurring items", "until", until.String()) + + items, err := r.repoRecur.ShouldRecur(until) if err != nil { return err } + r.logger.Info("found recurring items", "count", len(items)) for _, i := range items { r.logger.Info("processing recurring item", "id", i.ID) - // spawn instance newRecurNext := item.FirstRecurAfter(i.Recurrer, i.RecurNext) - newItem := i - newItem.ID = uuid.New().String() - newItem.Date = newRecurNext - newItem.Recurrer = nil - newItem.RecurNext = item.Date{} - if err := r.repoSync.Update(newItem, time.Now()); err != nil { - return err + + for { + if newRecurNext.After(until) { + break + } + + // spawn instance + newItem := i + newItem.ID = uuid.New().String() + newItem.Date = newRecurNext + newItem.Recurrer = nil + newItem.RecurNext = item.Date{} + if err := r.repoSync.Update(newItem, time.Now()); err != nil { + return err + } + r.logger.Info("spawned instance", "newID", newItem.ID, "date", newItem.Date) + + newRecurNext = item.FirstRecurAfter(i.Recurrer, newRecurNext) } - r.logger.Info("spawned instance", "newID", newItem.ID, "date", newItem.Date) // update recurrer i.RecurNext = newRecurNext diff --git a/sync/service/recur_test.go b/sync/service/recur_test.go index 75702b0..62534be 100644 --- a/sync/service/recur_test.go +++ b/sync/service/recur_test.go @@ -14,6 +14,7 @@ func TestRecur(t *testing.T) { now := time.Now() today := item.NewDate(2024, 1, 1) + until := today.Add(3) mem := NewMemory() rec := NewRecur(mem, mem, slog.New(slog.NewTextHandler(io.Discard, nil))) @@ -33,7 +34,7 @@ func TestRecur(t *testing.T) { } // Run recurrence - if err := rec.Recur(); err != nil { + if err := rec.Recur(until); err != nil { t.Errorf("Recur failed: %v", err) } @@ -43,14 +44,14 @@ func TestRecur(t *testing.T) { t.Errorf("failed to get updated items: %v", err) } - if len(items) != 2 { // Original + new instance + if len(items) != 4 { // Original + 3 new instances t.Errorf("expected 2 items, got %d", len(items)) } // Check that RecurNext was updated - recurItems, err := mem.ShouldRecur(today.Add(1)) + recurItems, err := mem.ShouldRecur(until.Add(1)) if err != nil { - t.Fatal(err) + t.Errorf("exp nil, got %v", err) } if len(recurItems) != 1 { t.Errorf("expected 1 recur item, got %d", len(recurItems)) diff --git a/sync/service/service.go b/sync/service/service.go index cfbefe2..8204b1a 100644 --- a/sync/service/service.go +++ b/sync/service/service.go @@ -19,6 +19,7 @@ var ( dbName = flag.String("dbname", "planner", "database name") dbUser = flag.String("dbuser", "test", "database user") dbPassword = flag.String("dbpassword", "test", "database password") + recurDays = flag.Int("recurdays", 8, "amount of days ahead to recur") ) func main() { @@ -39,7 +40,7 @@ func main() { "dbUser": *dbUser, }) recurrer := NewRecur(repo, repo, logger) - go recurrer.Run(6 * time.Hour) + go recurrer.Run(*recurDays, 6*time.Hour) srv := NewServer(repo, *apiKey, logger) go http.ListenAndServe(fmt.Sprintf(":%s", *apiPort), srv)