summaryrefslogtreecommitdiff
path: root/internal/handlers/cache.go
diff options
context:
space:
mode:
authorPeter Stone <thepeterstone@gmail.com>2026-01-23 21:37:18 -1000
committerPeter Stone <thepeterstone@gmail.com>2026-01-23 21:37:18 -1000
commit465093343ddd398ce5f6377fc9c472d8251c618b (patch)
treed333a2f1c8879f7b114817e929c95e9fcf5f4c3b /internal/handlers/cache.go
parente23c85577cbb0eac8b847dd989072698ff4e7a30 (diff)
Refactor: reduce code duplication with shared abstractions
- Add BaseClient HTTP abstraction (internal/api/http.go) to eliminate duplicated HTTP boilerplate across Todoist, Trello, and PlanToEat clients - Add response helpers (internal/handlers/response.go) for JSON/HTML responses - Add generic cache wrapper (internal/handlers/cache.go) using Go generics - Consolidate HandleCompleteAtom/HandleUncompleteAtom into handleAtomToggle - Merge TabsHandler into Handler, delete tabs.go - Extract sortTasksByUrgency and filterAndSortTrelloTasks helpers - Update tests to work with new BaseClient structure Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Diffstat (limited to 'internal/handlers/cache.go')
-rw-r--r--internal/handlers/cache.go52
1 files changed, 52 insertions, 0 deletions
diff --git a/internal/handlers/cache.go b/internal/handlers/cache.go
new file mode 100644
index 0000000..a2f534e
--- /dev/null
+++ b/internal/handlers/cache.go
@@ -0,0 +1,52 @@
+package handlers
+
+import (
+ "context"
+ "log"
+
+ "task-dashboard/internal/store"
+)
+
+// CacheFetcher defines the interface for fetching and caching data
+type CacheFetcher[T any] struct {
+ Store *store.Store
+ CacheKey string
+ TTLMinutes int
+ Fetch func(ctx context.Context) ([]T, error)
+ GetFromCache func() ([]T, error)
+ SaveToCache func([]T) error
+}
+
+// FetchWithCache fetches data from cache or API with fallback
+func (cf *CacheFetcher[T]) FetchWithCache(ctx context.Context, forceRefresh bool) ([]T, error) {
+ // Check cache validity
+ if !forceRefresh {
+ valid, err := cf.Store.IsCacheValid(cf.CacheKey)
+ if err == nil && valid {
+ return cf.GetFromCache()
+ }
+ }
+
+ // Fetch from API
+ data, err := cf.Fetch(ctx)
+ if err != nil {
+ // Try to return cached data even if stale
+ cachedData, cacheErr := cf.GetFromCache()
+ if cacheErr == nil && len(cachedData) > 0 {
+ return cachedData, nil
+ }
+ return nil, err
+ }
+
+ // Save to cache
+ if err := cf.SaveToCache(data); err != nil {
+ log.Printf("Failed to save to cache (%s): %v", cf.CacheKey, err)
+ }
+
+ // Update cache metadata
+ if err := cf.Store.UpdateCacheMetadata(cf.CacheKey, cf.TTLMinutes); err != nil {
+ log.Printf("Failed to update cache metadata (%s): %v", cf.CacheKey, err)
+ }
+
+ return data, nil
+}