diff options
| author | Peter Stone <thepeterstone@gmail.com> | 2026-01-23 21:37:18 -1000 |
|---|---|---|
| committer | Peter Stone <thepeterstone@gmail.com> | 2026-01-23 21:37:18 -1000 |
| commit | 465093343ddd398ce5f6377fc9c472d8251c618b (patch) | |
| tree | d333a2f1c8879f7b114817e929c95e9fcf5f4c3b /internal/handlers/cache.go | |
| parent | e23c85577cbb0eac8b847dd989072698ff4e7a30 (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.go | 52 |
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 +} |
