mirror of
https://github.com/status-im/status-go.git
synced 2025-02-27 14:10:54 +00:00
68 lines
1.1 KiB
Go
68 lines
1.1 KiB
Go
package market
|
|
|
|
import (
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
type cacheItem[V any] struct {
|
|
value V
|
|
expiration time.Time
|
|
}
|
|
|
|
type Cache[K comparable, V any] struct {
|
|
data map[K]cacheItem[V]
|
|
lock sync.RWMutex
|
|
ttl time.Duration
|
|
fetcher func(key K) (V, error)
|
|
}
|
|
|
|
func NewCache[K comparable, V any](ttl time.Duration, fetchFn func(key K) (V, error)) *Cache[K, V] {
|
|
return &Cache[K, V]{
|
|
data: make(map[K]cacheItem[V]),
|
|
ttl: ttl,
|
|
fetcher: fetchFn,
|
|
}
|
|
}
|
|
|
|
func (c *Cache[K, V]) Get(key K, fresh bool) (V, error) {
|
|
if fresh {
|
|
return c.refresh(key, fresh)
|
|
}
|
|
|
|
c.lock.RLock()
|
|
item, exists := c.data[key]
|
|
c.lock.RUnlock()
|
|
|
|
if exists && time.Now().Before(item.expiration) {
|
|
return item.value, nil
|
|
}
|
|
|
|
return c.refresh(key, fresh)
|
|
}
|
|
|
|
func (c *Cache[K, V]) refresh(key K, fresh bool) (V, error) {
|
|
c.lock.Lock()
|
|
defer c.lock.Unlock()
|
|
|
|
if !fresh {
|
|
item, exists := c.data[key]
|
|
if exists && time.Now().Before(item.expiration) {
|
|
return item.value, nil
|
|
}
|
|
}
|
|
|
|
value, err := c.fetcher(key)
|
|
if err != nil {
|
|
var zero V
|
|
return zero, err
|
|
}
|
|
|
|
c.data[key] = cacheItem[V]{
|
|
value: value,
|
|
expiration: time.Now().Add(c.ttl),
|
|
}
|
|
|
|
return value, nil
|
|
}
|