Files
open-im-server/pkg/localcache/lru/lru_lazy.go
T

91 lines
1.8 KiB
Go
Raw Normal View History

2024-01-15 15:23:42 +08:00
package lru
2024-01-15 11:42:18 +08:00
import (
"github.com/hashicorp/golang-lru/v2/simplelru"
"sync"
"time"
)
2024-01-22 21:14:21 +08:00
type layLruItem[V any] struct {
2024-01-15 11:42:18 +08:00
lock sync.Mutex
expires int64
err error
value V
}
2024-01-22 21:14:21 +08:00
func NewLayLRU[K comparable, V any](size int, successTTL, failedTTL time.Duration, target Target, onEvict EvictCallback[K, V]) *LayLRU[K, V] {
var cb simplelru.EvictCallback[K, *layLruItem[V]]
2024-01-15 11:42:18 +08:00
if onEvict != nil {
2024-01-22 21:14:21 +08:00
cb = func(key K, value *layLruItem[V]) {
2024-01-15 11:42:18 +08:00
onEvict(key, value.value)
}
}
2024-01-22 21:14:21 +08:00
core, err := simplelru.NewLRU[K, *layLruItem[V]](size, cb)
2024-01-15 11:42:18 +08:00
if err != nil {
panic(err)
}
2024-01-22 21:14:21 +08:00
return &LayLRU[K, V]{
2024-01-15 11:42:18 +08:00
core: core,
successTTL: successTTL,
failedTTL: failedTTL,
target: target,
}
}
2024-01-22 21:14:21 +08:00
type LayLRU[K comparable, V any] struct {
2024-01-15 11:42:18 +08:00
lock sync.Mutex
2024-01-22 21:14:21 +08:00
core *simplelru.LRU[K, *layLruItem[V]]
2024-01-15 11:42:18 +08:00
successTTL time.Duration
failedTTL time.Duration
target Target
}
2024-01-22 21:14:21 +08:00
func (x *LayLRU[K, V]) Get(key K, fetch func() (V, error)) (V, error) {
2024-01-15 11:42:18 +08:00
x.lock.Lock()
v, ok := x.core.Get(key)
if ok {
x.lock.Unlock()
v.lock.Lock()
expires, value, err := v.expires, v.value, v.err
if expires != 0 && expires > time.Now().UnixMilli() {
v.lock.Unlock()
x.target.IncrGetHit()
return value, err
}
} else {
2024-01-22 21:14:21 +08:00
v = &layLruItem[V]{}
2024-01-15 11:42:18 +08:00
x.core.Add(key, v)
v.lock.Lock()
x.lock.Unlock()
}
defer v.lock.Unlock()
if v.expires > time.Now().UnixMilli() {
return v.value, v.err
}
v.value, v.err = fetch()
if v.err == nil {
v.expires = time.Now().Add(x.successTTL).UnixMilli()
x.target.IncrGetSuccess()
} else {
v.expires = time.Now().Add(x.failedTTL).UnixMilli()
x.target.IncrGetFailed()
}
return v.value, v.err
}
2024-01-22 21:14:21 +08:00
func (x *LayLRU[K, V]) Del(key K) bool {
2024-01-15 11:42:18 +08:00
x.lock.Lock()
ok := x.core.Remove(key)
x.lock.Unlock()
2024-01-15 15:23:42 +08:00
if ok {
x.target.IncrDelHit()
} else {
x.target.IncrDelNotFound()
}
2024-01-15 11:42:18 +08:00
return ok
}
2024-01-22 21:14:21 +08:00
func (x *LayLRU[K, V]) Stop() {
2024-01-15 11:42:18 +08:00
}