1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
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
}
|