summaryrefslogtreecommitdiff
path: root/internal/handlers/handlers.go
diff options
context:
space:
mode:
authorPeter Stone <thepeterstone@gmail.com>2026-02-17 14:43:42 -1000
committerPeter Stone <thepeterstone@gmail.com>2026-02-17 14:43:42 -1000
commitec7d895c00c571b37ad9255b99b2e1756776c9e1 (patch)
tree31f8a925375fd5b00ee5febfe5d83f35487b1dd3 /internal/handlers/handlers.go
parent44fa97ce901bbfc5957e6d9ba90a53086bb5950b (diff)
Add calendar cache layer, incremental sync tests, completion assertions
- Google Calendar events now cached via CacheFetcher pattern with stale-cache fallback on API errors (new migration 015, store methods, fetchCalendarEvents handler, BuildTimeline reads from store) - Todoist incremental sync path covered by 5 new tests - Task completion tests assert response body, headers, and template data Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat (limited to 'internal/handlers/handlers.go')
-rw-r--r--internal/handlers/handlers.go23
1 files changed, 18 insertions, 5 deletions
diff --git a/internal/handlers/handlers.go b/internal/handlers/handlers.go
index 876326e..e06c35e 100644
--- a/internal/handlers/handlers.go
+++ b/internal/handlers/handlers.go
@@ -267,7 +267,7 @@ func (h *Handler) aggregateData(ctx context.Context, forceRefresh bool) (*models
if h.googleCalendarClient != nil {
fetch("Google Calendar", func() error {
- events, err := h.googleCalendarClient.GetUpcomingEvents(ctx, 10)
+ events, err := h.fetchCalendarEvents(ctx, false)
if err == nil {
mu.Lock()
data.Events = events
@@ -450,6 +450,22 @@ func (h *Handler) fetchMeals(ctx context.Context, forceRefresh bool) ([]models.M
return fetcher.FetchWithCache(ctx, forceRefresh)
}
+// fetchCalendarEvents fetches Google Calendar events from cache or API
+func (h *Handler) fetchCalendarEvents(ctx context.Context, forceRefresh bool) ([]models.CalendarEvent, error) {
+ if h.googleCalendarClient == nil {
+ return nil, nil
+ }
+ fetcher := &CacheFetcher[models.CalendarEvent]{
+ Store: h.store,
+ CacheKey: store.CacheKeyGoogleCalendar,
+ TTLMinutes: h.config.CacheTTLMinutes,
+ Fetch: func(ctx context.Context) ([]models.CalendarEvent, error) { return h.googleCalendarClient.GetUpcomingEvents(ctx, 50) },
+ GetFromCache: h.store.GetCalendarEvents,
+ SaveToCache: h.store.SaveCalendarEvents,
+ }
+ return fetcher.FetchWithCache(ctx, forceRefresh)
+}
+
// fetchBoards fetches Trello boards from cache or API
func (h *Handler) fetchBoards(ctx context.Context, forceRefresh bool) ([]models.Board, error) {
fetcher := &CacheFetcher[models.Board]{
@@ -999,10 +1015,7 @@ func (h *Handler) HandleTabPlanning(w http.ResponseWriter, r *http.Request) {
boards, _ := h.store.GetBoards()
tasks, _ := h.store.GetTasks()
- var events []models.CalendarEvent
- if h.googleCalendarClient != nil {
- events, _ = h.googleCalendarClient.GetUpcomingEvents(r.Context(), 20)
- }
+ events, _ := h.fetchCalendarEvents(r.Context(), false)
var scheduled []ScheduledItem
var unscheduled []models.Atom