2023-02-17 15:36:54 +00:00
|
|
|
package cachemanager
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2023-10-26 13:38:31 +00:00
|
|
|
"errors"
|
2023-02-17 15:36:54 +00:00
|
|
|
"github.com/fthvgb1/wp-go/cache"
|
2023-10-26 13:38:31 +00:00
|
|
|
str "github.com/fthvgb1/wp-go/helper/strings"
|
|
|
|
"github.com/fthvgb1/wp-go/safety"
|
2023-02-17 15:36:54 +00:00
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
var ctx = context.Background()
|
|
|
|
|
2023-10-26 13:38:31 +00:00
|
|
|
var mapFlush = safety.NewMap[string, func(any)]()
|
|
|
|
var getSingleFn = safety.NewMap[string, func(context.Context, any, time.Duration, ...any) (any, error)]()
|
|
|
|
var getBatchFn = safety.NewMap[string, func(context.Context, any, time.Duration, ...any) (any, error)]()
|
|
|
|
var anyFlush = safety.NewMap[string, func()]()
|
|
|
|
|
2023-02-17 15:36:54 +00:00
|
|
|
type flush interface {
|
|
|
|
Flush(ctx context.Context)
|
|
|
|
}
|
|
|
|
|
2023-10-26 13:38:31 +00:00
|
|
|
type clearExpired interface {
|
2023-02-17 15:36:54 +00:00
|
|
|
ClearExpired(ctx context.Context)
|
|
|
|
}
|
|
|
|
|
2023-10-26 13:38:31 +00:00
|
|
|
var clears []clearExpired
|
2023-02-17 15:36:54 +00:00
|
|
|
|
|
|
|
var flushes []flush
|
|
|
|
|
|
|
|
func Flush() {
|
|
|
|
for _, f := range flushes {
|
|
|
|
f.Flush(ctx)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-27 12:51:46 +00:00
|
|
|
func FlushMapVal[T any](name string, keys ...T) {
|
2023-10-26 13:38:31 +00:00
|
|
|
v, ok := mapFlush.Load(name)
|
2023-10-27 12:51:46 +00:00
|
|
|
if !ok || len(keys) < 1 {
|
2023-10-26 13:38:31 +00:00
|
|
|
return
|
|
|
|
}
|
2023-10-27 12:51:46 +00:00
|
|
|
v(keys)
|
2023-10-26 13:38:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func FlushAnyVal(name ...string) {
|
|
|
|
for _, s := range name {
|
|
|
|
v, ok := anyFlush.Load(s)
|
|
|
|
if ok {
|
|
|
|
v()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func pushFlushMap[K comparable, V any](m *cache.MapCache[K, V], args ...any) {
|
|
|
|
name := parseArgs(args...)
|
|
|
|
if name != "" {
|
|
|
|
anyFlush.Store(name, func() {
|
|
|
|
m.Flush(ctx)
|
|
|
|
})
|
|
|
|
mapFlush.Store(name, func(a any) {
|
2023-10-27 12:51:46 +00:00
|
|
|
k, ok := a.([]K)
|
|
|
|
if ok && len(k) > 0 {
|
|
|
|
m.Del(ctx, k...)
|
2023-10-26 13:38:31 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
getSingleFn.Store(name, func(ct context.Context, k any, t time.Duration, a ...any) (any, error) {
|
|
|
|
kk, ok := k.(K)
|
|
|
|
if !ok {
|
|
|
|
return nil, errors.New(str.Join("cache ", name, " key type err"))
|
|
|
|
}
|
|
|
|
return m.GetCache(ct, kk, t, a...)
|
|
|
|
})
|
|
|
|
getBatchFn.Store(name, func(ct context.Context, k any, t time.Duration, a ...any) (any, error) {
|
|
|
|
kk, ok := k.([]K)
|
|
|
|
if !ok {
|
|
|
|
return nil, errors.New(str.Join("cache ", name, " key type err"))
|
|
|
|
}
|
|
|
|
return m.GetCacheBatch(ct, kk, t, a...)
|
|
|
|
})
|
|
|
|
FlushPush()
|
|
|
|
}
|
2023-02-17 15:36:54 +00:00
|
|
|
}
|
2023-10-26 13:38:31 +00:00
|
|
|
|
|
|
|
func Get[T, K any](name string, ct context.Context, key K, timeout time.Duration, params ...any) (r T, err error) {
|
|
|
|
v, ok := getSingleFn.Load(name)
|
|
|
|
if !ok {
|
|
|
|
err = errors.New(str.Join("cache ", name, " doesn't exist"))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
vv, err := v(ct, key, timeout, params...)
|
|
|
|
if err != nil {
|
|
|
|
return r, err
|
|
|
|
}
|
|
|
|
r = vv.(T)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
func GetMultiple[T, K any](name string, ct context.Context, key []K, timeout time.Duration, params ...any) (r []T, err error) {
|
|
|
|
v, ok := getBatchFn.Load(name)
|
|
|
|
if !ok {
|
|
|
|
err = errors.New(str.Join("cache ", name, " doesn't exist"))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
vv, err := v(ct, key, timeout, params...)
|
|
|
|
if err != nil {
|
|
|
|
return r, err
|
|
|
|
}
|
|
|
|
r = vv.([]T)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func parseArgs(args ...any) string {
|
|
|
|
var name string
|
|
|
|
for _, arg := range args {
|
|
|
|
v, ok := arg.(string)
|
|
|
|
if ok {
|
|
|
|
name = v
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return name
|
|
|
|
}
|
|
|
|
|
2023-10-27 12:51:46 +00:00
|
|
|
func NewMapCache[K comparable, V any](data cache.Cache[K, V], batchFn cache.MapBatchFn[K, V], fn cache.MapSingleFn[K, V], args ...any) *cache.MapCache[K, V] {
|
|
|
|
m := cache.NewMapCache[K, V](data, fn, batchFn)
|
2023-10-26 13:38:31 +00:00
|
|
|
pushFlushMap(m, args...)
|
2023-02-17 15:36:54 +00:00
|
|
|
FlushPush(m)
|
|
|
|
ClearPush(m)
|
|
|
|
return m
|
|
|
|
}
|
2023-10-26 13:38:31 +00:00
|
|
|
func NewMemoryMapCache[K comparable, V any](batchFn cache.MapBatchFn[K, V],
|
|
|
|
fn cache.MapSingleFn[K, V], expireTime time.Duration, args ...any) *cache.MapCache[K, V] {
|
2023-10-27 12:51:46 +00:00
|
|
|
return NewMapCache[K, V](cache.NewMemoryMapCache[K, V](expireTime), batchFn, fn, args...)
|
2023-10-26 13:38:31 +00:00
|
|
|
}
|
2023-02-17 15:36:54 +00:00
|
|
|
|
|
|
|
func FlushPush(f ...flush) {
|
|
|
|
flushes = append(flushes, f...)
|
|
|
|
}
|
2023-10-26 13:38:31 +00:00
|
|
|
func ClearPush(c ...clearExpired) {
|
2023-02-17 15:36:54 +00:00
|
|
|
clears = append(clears, c...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func ClearExpired() {
|
|
|
|
for _, c := range clears {
|
|
|
|
c.ClearExpired(ctx)
|
|
|
|
}
|
|
|
|
}
|