wp-go/cache/cachemanager/manger.go

164 lines
3.7 KiB
Go

package cachemanager
import (
"context"
"github.com/fthvgb1/wp-go/cache"
"github.com/fthvgb1/wp-go/cache/reload"
"github.com/fthvgb1/wp-go/helper"
"github.com/fthvgb1/wp-go/helper/slice/mockmap"
str "github.com/fthvgb1/wp-go/helper/strings"
"github.com/fthvgb1/wp-go/safety"
"runtime"
"sync"
"time"
)
var mutex sync.Mutex
type Fn func(context.Context)
type clearExpired interface {
ClearExpired(ctx context.Context)
}
var clears = safety.NewVar(mockmap.Map[string, Fn]{})
var flushes = safety.NewVar(mockmap.Map[string, Fn]{})
func Flush() {
ctx := context.WithValue(context.Background(), "execFlushBy", "mangerFlushFn")
for _, f := range flushes.Load() {
f.Value(ctx)
}
}
func Flushes(ctx context.Context, names ...string) {
execute(ctx, flushes, names...)
}
func execute(ctx context.Context, q *safety.Var[mockmap.Map[string, Fn]], names ...string) {
queues := q.Load()
for _, name := range names {
queue := queues.Get(name)
if queue.Value != nil {
queue.Value(ctx)
}
}
}
func parseArgs(args ...any) (string, func() time.Duration) {
var name string
var fn func() time.Duration
for _, arg := range args {
v, ok := arg.(string)
if ok {
name = v
continue
}
vv, ok := arg.(func() time.Duration)
if ok {
fn = vv
}
}
return name, fn
}
func buildLockFn[K comparable](args ...any) cache.LockFn[K] {
lockFn := helper.ParseArgs(cache.LockFn[K](nil), args...)
name := helper.ParseArgs("", args...)
num := helper.ParseArgs(runtime.NumCPU(), args...)
loFn := func() int {
return num
}
loFn = helper.ParseArgs(loFn, args...)
if name != "" {
loFn = reload.BuildFnVal(str.Join("cachesLocksNum-", name), num, loFn)
}
if lockFn == nil {
looo := helper.ParseArgs(cache.Lockss[K](nil), args...)
if looo != nil {
lockFn = looo.GetLock
loo, ok := any(looo).(cache.LocksNum)
if ok && loo != nil {
loo.SetLockNum(num)
}
} else {
lo := cache.NewLocks[K](loFn)
lockFn = lo.GetLock
PushOrSetFlush(mockmap.Item[string, Fn]{
Name: name,
Value: lo.Flush,
})
}
}
return lockFn
}
func SetExpireTime(c cache.SetTime, name string, expireTime time.Duration, expireTimeFn func() time.Duration) {
if name == "" {
return
}
fn := reload.BuildFnVal(str.Join("cacheManger-", name, "-expiredTime"), expireTime, expireTimeFn)
c.SetExpiredTime(fn)
}
func ChangeExpireTime(t time.Duration, coverConf bool, name ...string) {
for _, s := range name {
reload.SetFnVal(s, t, coverConf)
}
}
func pushOrSet(q *safety.Var[mockmap.Map[string, Fn]], queues ...mockmap.Item[string, Fn]) {
mutex.Lock()
defer mutex.Unlock()
qu := q.Load()
for _, queue := range queues {
v := qu.Get(queue.Name)
if v.Value != nil {
qu.Set(queue.Name, queue.Value)
} else {
qu = append(qu, queue)
}
}
q.Store(qu)
}
// PushOrSetFlush will execute flush func when call Flush or Flushes
func PushOrSetFlush(queues ...mockmap.Item[string, Fn]) {
pushOrSet(flushes, queues...)
}
// PushOrSetClearExpired will execute clearExpired func when call ClearExpired or ClearExpireds
func PushOrSetClearExpired(queues ...mockmap.Item[string, Fn]) {
pushOrSet(clears, queues...)
}
func del(q *safety.Var[mockmap.Map[string, Fn]], names ...string) {
mutex.Lock()
defer mutex.Unlock()
queues := q.Load()
for _, name := range names {
queues.Del(name)
}
q.Store(queues)
}
func DelFlush(names ...string) {
del(flushes, names...)
}
func DelClearExpired(names ...string) {
del(clears, names...)
}
func ClearExpireds(ctx context.Context, names ...string) {
execute(ctx, clears, names...)
}
func ClearExpired() {
ctx := context.WithValue(context.Background(), "execClearExpired", "mangerClearExpiredFn")
for _, queue := range clears.Load() {
queue.Value(ctx)
}
}