2025-04-21 11:07:53 -05:00
|
|
|
package ezcache
|
|
|
|
|
|
|
|
|
|
import (
|
2025-04-21 12:01:32 -05:00
|
|
|
"sync"
|
2025-04-21 11:07:53 -05:00
|
|
|
"time"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type ezc[K comparable, V any] struct {
|
2025-04-21 12:01:32 -05:00
|
|
|
fetch Fetcher[K, V]
|
|
|
|
|
exp time.Duration
|
|
|
|
|
cache map[K]V
|
|
|
|
|
setTime map[K]time.Time
|
|
|
|
|
lock sync.RWMutex
|
|
|
|
|
timeLock sync.RWMutex
|
2025-04-21 11:07:53 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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) {
|
2025-04-21 12:01:32 -05:00
|
|
|
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
|
2025-04-21 11:07:53 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 {
|
2025-04-21 11:24:51 -05:00
|
|
|
return ErrInvalidExpiry
|
2025-04-21 11:07:53 -05:00
|
|
|
}
|
|
|
|
|
c.exp = exp
|
|
|
|
|
return nil
|
|
|
|
|
}
|