package cache import ( "sync" "time" "gitblog/internal/content" "github.com/patrickmn/go-cache" ) type Manager struct { cache *cache.Cache mutex sync.RWMutex } func NewManager(defaultExpiration, cleanupInterval time.Duration) *Manager { return &Manager{ cache: cache.New(defaultExpiration, cleanupInterval), } } func (m *Manager) Set(key string, value interface{}, expiration time.Duration) { m.mutex.Lock() defer m.mutex.Unlock() m.cache.Set(key, value, expiration) } func (m *Manager) Get(key string) (interface{}, bool) { m.mutex.RLock() defer m.mutex.RUnlock() return m.cache.Get(key) } func (m *Manager) GetPost(slug string) (*content.Post, bool) { if item, found := m.Get("post:" + slug); found { if post, ok := item.(*content.Post); ok { return post, true } } return nil, false } func (m *Manager) SetPost(slug string, post *content.Post, expiration time.Duration) { m.Set("post:"+slug, post, expiration) } func (m *Manager) GetPosts() ([]*content.Post, bool) { if item, found := m.Get("posts:all"); found { if posts, ok := item.([]*content.Post); ok { return posts, true } } return nil, false } func (m *Manager) SetPosts(posts []*content.Post, expiration time.Duration) { m.Set("posts:all", posts, expiration) } func (m *Manager) GetPostsByCategory(category string) ([]*content.Post, bool) { if item, found := m.Get("posts:category:" + category); found { if posts, ok := item.([]*content.Post); ok { return posts, true } } return nil, false } func (m *Manager) SetPostsByCategory(category string, posts []*content.Post, expiration time.Duration) { m.Set("posts:category:"+category, posts, expiration) } func (m *Manager) GetPage(path string) (*content.Page, bool) { if item, found := m.Get("page:" + path); found { if page, ok := item.(*content.Page); ok { return page, true } } return nil, false } func (m *Manager) SetPage(path string, page *content.Page, expiration time.Duration) { m.Set("page:"+path, page, expiration) } func (m *Manager) GetNavigation() ([]content.Navigation, bool) { if item, found := m.Get("navigation"); found { if nav, ok := item.([]content.Navigation); ok { return nav, true } } return nil, false } func (m *Manager) SetNavigation(nav []content.Navigation, expiration time.Duration) { m.Set("navigation", nav, expiration) } func (m *Manager) Invalidate(pattern string) { m.mutex.Lock() defer m.mutex.Unlock() items := m.cache.Items() for key := range items { if pattern == "" || contains(key, pattern) { m.cache.Delete(key) } } } func (m *Manager) Clear() { m.mutex.Lock() defer m.mutex.Unlock() m.cache.Flush() } func contains(s, substr string) bool { return len(s) >= len(substr) && s[:len(substr)] == substr }