wp-go/cache/memorymapcache.go

102 lines
2.1 KiB
Go
Raw Permalink Normal View History

2023-02-02 11:16:18 +00:00
package cache
import (
"context"
"github.com/fthvgb1/wp-go/safety"
2023-02-02 14:56:09 +00:00
"sync"
2023-02-02 11:16:18 +00:00
"time"
)
type MemoryMapCache[K comparable, V any] struct {
safety.Map[K, mapVal[V]]
}
2023-02-02 14:56:09 +00:00
func NewMemoryMapCacheByFn[K comparable, V any](fn func(...any) (V, error), expireTime time.Duration) *MapCache[K, V] {
return &MapCache[K, V]{
data: NewMemoryMapCache[K, V](),
cacheFunc: fn,
expireTime: expireTime,
mux: sync.Mutex{},
}
}
func NewMemoryMapCacheByBatchFn[K comparable, V any](fn func(...any) (map[K]V, error), expireTime time.Duration) *MapCache[K, V] {
r := &MapCache[K, V]{
data: NewMemoryMapCache[K, V](),
batchCacheFn: fn,
expireTime: expireTime,
mux: sync.Mutex{},
}
r.setCacheFn(fn)
return r
}
2023-02-02 11:16:18 +00:00
func NewMemoryMapCache[K comparable, V any]() *MemoryMapCache[K, V] {
return &MemoryMapCache[K, V]{Map: safety.NewMap[K, mapVal[V]]()}
}
type mapVal[T any] struct {
setTime time.Time
ver int
data T
}
func (m *MemoryMapCache[K, V]) Get(_ context.Context, key K) (r V, ok bool) {
v, ok := m.Load(key)
if ok {
return v.data, true
}
return
}
func (m *MemoryMapCache[K, V]) Set(_ context.Context, key K, val V, _ time.Duration) {
v, ok := m.Load(key)
t := time.Now()
if ok {
v.data = val
v.setTime = t
v.ver++
} else {
v = mapVal[V]{
setTime: t,
ver: 1,
data: val,
}
}
m.Store(key, v)
}
func (m *MemoryMapCache[K, V]) Ttl(_ context.Context, key K, expire time.Duration) time.Duration {
v, ok := m.Load(key)
if !ok {
2023-02-02 14:56:09 +00:00
return time.Duration(-1)
2023-02-02 11:16:18 +00:00
}
2023-02-02 14:56:09 +00:00
return expire - time.Now().Sub(v.setTime)
2023-02-02 11:16:18 +00:00
}
func (m *MemoryMapCache[K, V]) Ver(_ context.Context, key K) int {
v, ok := m.Load(key)
if !ok {
return -1
}
return v.ver
}
func (m *MemoryMapCache[K, V]) Flush(context.Context) {
m.Map = safety.NewMap[K, mapVal[V]]()
}
func (m *MemoryMapCache[K, V]) Delete(_ context.Context, key K) {
m.Map.Delete(key)
}
func (m *MemoryMapCache[K, V]) ClearExpired(_ context.Context, expire time.Duration) {
now := time.Duration(time.Now().UnixNano())
m.Range(func(k K, v mapVal[V]) bool {
if now > time.Duration(v.setTime.UnixNano())+expire {
m.Map.Delete(k)
}
return true
})
}