summaryrefslogtreecommitdiff
path: root/internal/handlers/cache.go
blob: a2f534edc09f0eb19fa63a72f8450c267d93d0db (plain)
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
}