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 }