package cache import ( "bytes" "compress/gzip" "sync" "time" ) // Cache stores generated HTML pages type Cache struct { pages map[string]*CachedPage mu sync.RWMutex } // NewCache creates a new cache func NewCache() *Cache { return &Cache{ pages: make(map[string]*CachedPage), } } // Get retrieves a page from cache func (c *Cache) Get(path string) (*CachedPage, bool) { c.mu.RLock() defer c.mu.RUnlock() page, exists := c.pages[path] return page, exists } // Set stores a page in cache func (c *Cache) Set(path string, content string) error { c.mu.Lock() defer c.mu.Unlock() // Generate ETag etag := GenerateETag(content) // Pre-compress content var compressed bytes.Buffer writer := gzip.NewWriter(&compressed) if _, err := writer.Write([]byte(content)); err != nil { return err } if err := writer.Close(); err != nil { return err } c.pages[path] = &CachedPage{ Content: content, ETag: etag, LastUpdated: time.Now(), Compressed: compressed.Bytes(), } return nil } // Delete removes a page from cache func (c *Cache) Delete(path string) { c.mu.Lock() defer c.mu.Unlock() delete(c.pages, path) } // Clear clears all cached pages func (c *Cache) Clear() { c.mu.Lock() defer c.mu.Unlock() c.pages = make(map[string]*CachedPage) } // Size returns the number of cached pages func (c *Cache) Size() int { c.mu.RLock() defer c.mu.RUnlock() return len(c.pages) } // GetAllPaths returns all cached page paths func (c *Cache) GetAllPaths() []string { c.mu.RLock() defer c.mu.RUnlock() paths := make([]string, 0, len(c.pages)) for path := range c.pages { paths = append(paths, path) } return paths }