ezcache/ezcache.go
2025-04-21 12:01:32 -05:00

76 lines
1.3 KiB
Go

package ezcache
import (
"sync"
"time"
)
type ezc[K comparable, V any] struct {
fetch Fetcher[K, V]
exp time.Duration
cache map[K]V
setTime map[K]time.Time
lock sync.RWMutex
timeLock sync.RWMutex
}
func New[K comparable, V any](fetcher Fetcher[K, V], exp time.Duration) (Cache[K, V], error) {
c := &ezc[K, V]{}
err := c.SetFetcher(fetcher)
if err != nil {
return nil, err
}
err = c.SetExpiry(exp)
if err != nil {
return nil, err
}
c.cache = make(map[K]V)
c.setTime = make(map[K]time.Time)
return c, nil
}
func (c *ezc[K, V]) Get(key K) (V, error) {
c.timeLock.RLock()
setTime, ok := c.setTime[key]
c.timeLock.RUnlock()
if ok && time.Since(setTime) <= c.exp {
c.lock.RLock()
val, ok := c.cache[key]
c.lock.RUnlock()
if ok {
return val, nil
}
}
val, err := c.fetch(key)
if err != nil {
return val, err
}
c.lock.Lock()
defer c.lock.Unlock()
c.cache[key] = val
c.timeLock.Lock()
defer c.timeLock.Unlock()
c.setTime[key] = time.Now()
return val, nil
}
func (c *ezc[K, V]) SetFetcher(f Fetcher[K, V]) error {
if f == nil {
return ErrInvalidFetcher
}
c.fetch = f
return nil
}
func (c *ezc[K, V]) SetExpiry(exp time.Duration) error {
if exp <= 0 {
return ErrInvalidExpiry
}
c.exp = exp
return nil
}