102 lines
1.9 KiB
Go
102 lines
1.9 KiB
Go
package result
|
|
|
|
import (
|
|
"seanime/internal/constants"
|
|
"seanime/internal/util"
|
|
"time"
|
|
)
|
|
|
|
type Cache[K interface{}, V any] struct {
|
|
store util.RWMutexMap
|
|
}
|
|
|
|
type cacheItem[K interface{}, V any] struct {
|
|
value V
|
|
expiration time.Time
|
|
}
|
|
|
|
func NewCache[K interface{}, V any]() *Cache[K, V] {
|
|
return &Cache[K, V]{}
|
|
}
|
|
|
|
func (c *Cache[K, V]) Set(key K, value V) {
|
|
ttl := constants.GcTime
|
|
c.store.Store(key, &cacheItem[K, V]{value, time.Now().Add(ttl)})
|
|
go func() {
|
|
<-time.After(ttl)
|
|
c.Delete(key)
|
|
}()
|
|
}
|
|
|
|
func (c *Cache[K, V]) SetT(key K, value V, ttl time.Duration) {
|
|
c.store.Store(key, &cacheItem[K, V]{value, time.Now().Add(ttl)})
|
|
go func() {
|
|
<-time.After(ttl)
|
|
c.Delete(key)
|
|
}()
|
|
}
|
|
|
|
func (c *Cache[K, V]) Get(key K) (V, bool) {
|
|
item, ok := c.store.Load(key)
|
|
if !ok {
|
|
return (&cacheItem[K, V]{}).value, false
|
|
}
|
|
ci := item.(*cacheItem[K, V])
|
|
if time.Now().After(ci.expiration) {
|
|
c.Delete(key)
|
|
return (&cacheItem[K, V]{}).value, false
|
|
}
|
|
return ci.value, true
|
|
}
|
|
|
|
func (c *Cache[K, V]) Pop() (K, V, bool) {
|
|
var key K
|
|
var value V
|
|
var ok bool
|
|
c.store.Range(func(k, v interface{}) bool {
|
|
key = k.(K)
|
|
value = v.(*cacheItem[K, V]).value
|
|
ok = true
|
|
c.store.Delete(k)
|
|
return false
|
|
})
|
|
return key, value, ok
|
|
}
|
|
|
|
func (c *Cache[K, V]) Has(key K) bool {
|
|
_, ok := c.store.Load(key)
|
|
return ok
|
|
}
|
|
|
|
func (c *Cache[K, V]) GetOrSet(key K, createFunc func() (V, error)) (V, error) {
|
|
value, ok := c.Get(key)
|
|
if ok {
|
|
return value, nil
|
|
}
|
|
|
|
newValue, err := createFunc()
|
|
if err != nil {
|
|
return newValue, err
|
|
}
|
|
c.Set(key, newValue)
|
|
return newValue, nil
|
|
}
|
|
|
|
func (c *Cache[K, V]) Delete(key K) {
|
|
c.store.Delete(key)
|
|
}
|
|
|
|
func (c *Cache[K, V]) Clear() {
|
|
c.store.Range(func(key interface{}, value interface{}) bool {
|
|
c.store.Delete(key)
|
|
return true
|
|
})
|
|
}
|
|
|
|
func (c *Cache[K, V]) Range(callback func(key K, value V) bool) {
|
|
c.store.Range(func(key, value interface{}) bool {
|
|
ci := value.(*cacheItem[K, V])
|
|
return callback(key.(K), ci.value)
|
|
})
|
|
}
|