// Package cache provides application-level caching for CV and UI data. // Data is loaded once at startup and accessed via language key. package cache import ( "fmt" "sync" cvmodel "github.com/juanatsap/cv-site/internal/models/cv" uimodel "github.com/juanatsap/cv-site/internal/models/ui" ) // DataCache holds pre-loaded CV and UI data for all supported languages. // Thread-safe for concurrent read access. type DataCache struct { cv map[string]*cvmodel.CV ui map[string]*uimodel.UI mu sync.RWMutex } // New creates and initializes a DataCache with data for the given languages. // Returns error if any language fails to load - fail fast at startup. func New(languages []string) (*DataCache, error) { cache := &DataCache{ cv: make(map[string]*cvmodel.CV, len(languages)), ui: make(map[string]*uimodel.UI, len(languages)), } for _, lang := range languages { cv, err := cvmodel.LoadCV(lang) if err != nil { return nil, fmt.Errorf("load CV for '%s': %w", lang, err) } ui, err := uimodel.LoadUI(lang) if err != nil { return nil, fmt.Errorf("load UI for '%s': %w", lang, err) } cache.cv[lang] = cv cache.ui[lang] = ui } return cache, nil } // GetCV returns cached CV data for the given language. // Returns nil if language not found. func (c *DataCache) GetCV(lang string) *cvmodel.CV { c.mu.RLock() defer c.mu.RUnlock() return c.cv[lang] } // GetUI returns cached UI data for the given language. // Returns nil if language not found. func (c *DataCache) GetUI(lang string) *uimodel.UI { c.mu.RLock() defer c.mu.RUnlock() return c.ui[lang] } // Languages returns all cached language codes. func (c *DataCache) Languages() []string { c.mu.RLock() defer c.mu.RUnlock() langs := make([]string, 0, len(c.cv)) for lang := range c.cv { langs = append(langs, lang) } return langs }