Files
DockerBot/internal/cache/cache.go
2026-04-13 21:42:04 +02:00

84 lines
1.6 KiB
Go

package cache
import (
"sync"
"time"
"fergalla.com/dockerbot/internal/docker"
)
type ContainerCache struct {
mu sync.RWMutex
data []docker.ContainerBasicInfo
expiresAt time.Time
ttl time.Duration
// función para obtener datos frescos
fetchFunc func() ([]docker.ContainerBasicInfo, error)
}
// Constructor
func NewContainerCache(ttl time.Duration, fetch func() ([]docker.ContainerBasicInfo, error)) *ContainerCache {
return &ContainerCache{
ttl: ttl,
fetchFunc: fetch,
}
}
// Get devuelve datos cacheados o refresca si ha expirado
func (c *ContainerCache) Get() ([]docker.ContainerBasicInfo, error) {
// 🔍 lectura rápida
c.mu.RLock()
if time.Now().Before(c.expiresAt) && c.data != nil {
data := c.data
c.mu.RUnlock()
return data, nil
}
c.mu.RUnlock()
// 🔒 lock de escritura (refresco)
c.mu.Lock()
defer c.mu.Unlock()
// ⚠️ doble check (evita refrescos duplicados)
if time.Now().Before(c.expiresAt) && c.data != nil {
return c.data, nil
}
data, err := c.fetchFunc()
if err != nil {
return nil, err
}
c.data = data
c.expiresAt = time.Now().Add(c.ttl)
return c.data, nil
}
// Invalidate fuerza limpieza de cache
func (c *ContainerCache) Invalidate() {
c.mu.Lock()
defer c.mu.Unlock()
c.data = nil
c.expiresAt = time.Time{}
}
// ForceRefresh fuerza actualización inmediata
func (c *ContainerCache) ForceRefresh() ([]docker.ContainerBasicInfo, error) {
c.mu.Lock()
defer c.mu.Unlock()
data, err := c.fetchFunc()
if err != nil {
return nil, err
}
c.data = data
c.expiresAt = time.Now().Add(c.ttl)
return c.data, nil
}