84 lines
1.6 KiB
Go
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
|
|
}
|