optimize reload schema and optimize cachemanager package
This commit is contained in:
parent
e2e6bcc8ce
commit
5eaf798a6c
|
@ -6,6 +6,7 @@ import (
|
|||
"fmt"
|
||||
"github.com/fthvgb1/wp-go/app/pkg/config"
|
||||
"github.com/fthvgb1/wp-go/app/pkg/dao"
|
||||
"github.com/fthvgb1/wp-go/app/pkg/logs"
|
||||
"github.com/fthvgb1/wp-go/app/theme/wp"
|
||||
"github.com/fthvgb1/wp-go/cache/cachemanager"
|
||||
"github.com/fthvgb1/wp-go/cache/reload"
|
||||
|
@ -14,7 +15,7 @@ import (
|
|||
"github.com/fthvgb1/wp-go/helper/strings"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"strconv"
|
||||
strings2 "strings"
|
||||
str "strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
@ -58,7 +59,6 @@ func (r *RdmCache[K, V]) Set(ctx context.Context, key K, val V) {
|
|||
return
|
||||
}
|
||||
fmt.Println(result, err)
|
||||
|
||||
}
|
||||
|
||||
func (r *RdmCache[K, V]) GetExpireTime(ctx context.Context) time.Duration {
|
||||
|
@ -74,7 +74,7 @@ func (r *RdmCache[K, V]) Ttl(ctx context.Context, key K) time.Duration {
|
|||
}
|
||||
|
||||
func (r *RdmCache[K, V]) Flush(ctx context.Context) {
|
||||
|
||||
fmt.Println("flush redis cache")
|
||||
}
|
||||
|
||||
func (r *RdmCache[K, V]) Del(ctx context.Context, key ...K) {
|
||||
|
@ -82,12 +82,13 @@ func (r *RdmCache[K, V]) Del(ctx context.Context, key ...K) {
|
|||
}
|
||||
|
||||
func (r *RdmCache[K, V]) ClearExpired(ctx context.Context) {
|
||||
|
||||
fmt.Println("clear expired redis cache")
|
||||
}
|
||||
// use step:
|
||||
//1 go build -gcflags all="-N -l" --race -buildmode=plugin -o redisCache.so main.go && cp ./redisCache.so wp-go/plugins/
|
||||
//2 wp-go config add redisCache plugin
|
||||
func Re(h *wp.Handle) {
|
||||
|
||||
// RedisCache use step:
|
||||
// 1 go build -gcflags all="-N -l" --race -buildmode=plugin -o redisCache.so main.go && cp ./redisCache.so ../wp-go/plugins/
|
||||
// 2 wp-go config add redisCache plugin
|
||||
func RedisCache(h *wp.Handle) {
|
||||
vv, ok := cachemanager.GetMapCache[string, dao.PostIds]("listPostIds")
|
||||
if ok {
|
||||
_, ok := any(vv.Cache).(*RdmCache[string, dao.PostIds])
|
||||
|
@ -96,7 +97,14 @@ func Re(h *wp.Handle) {
|
|||
}
|
||||
}
|
||||
reload.AppendOnceFn(func() {
|
||||
cachemanager.SetMapCache("listPostIds",vv)
|
||||
err := cachemanager.SetMapCache("listPostIds", vv)
|
||||
if err != nil {
|
||||
logs.Error(err, "set recovery listPostIds cache err")
|
||||
} else {
|
||||
cachemanager.PushOrSetFlush(cachemanager.Queue{Name: "listPostIds", Fn: vv.Flush})
|
||||
cachemanager.PushOrSetClearExpired(cachemanager.Queue{Name: "listPostIds", Fn: vv.Flush})
|
||||
fmt.Println("recovery listPostIds cache ok")
|
||||
}
|
||||
})
|
||||
rdm := redis.NewClient(&redis.Options{
|
||||
Addr: "localhost:6379",
|
||||
|
@ -114,14 +122,14 @@ func Re(h *wp.Handle) {
|
|||
name: "",
|
||||
resFn: func(m map[string]string) dao.PostIds {
|
||||
return dao.PostIds{
|
||||
Ids: slice.Map(strings2.Split(m["ids"], ","), strings.ToInt[uint64]),
|
||||
Ids: slice.Map(str.Split(m["ids"], ","), strings.ToInt[uint64]),
|
||||
Length: strings.ToInt[int](m["length"]),
|
||||
}
|
||||
},
|
||||
saveData: func(ids dao.PostIds) map[string]string {
|
||||
t := slice.Map(ids.Ids, number.IntToString[uint64])
|
||||
return map[string]string{
|
||||
"ids": strings2.Join(t, ","),
|
||||
"ids": str.Join(t, ","),
|
||||
"length": strconv.Itoa(ids.Length),
|
||||
}
|
||||
},
|
||||
|
|
|
@ -87,6 +87,8 @@ type HandleCall struct {
|
|||
Name string
|
||||
}
|
||||
|
||||
var isFirstRequest = true
|
||||
|
||||
func SetConfigHandle(a ...any) Handle {
|
||||
configFn := a[0].(func(*Handle))
|
||||
hh := a[1].(*Handle)
|
||||
|
@ -100,6 +102,11 @@ func SetConfigHandle(a ...any) Handle {
|
|||
h.ginH = gin.H{}
|
||||
fnMap.Flush()
|
||||
fnHook.Flush()
|
||||
if isFirstRequest {
|
||||
isFirstRequest = false
|
||||
} else {
|
||||
reload.Reload()
|
||||
}
|
||||
h.C = hh.C
|
||||
h.theme = hh.theme
|
||||
configFn(h)
|
||||
|
@ -108,7 +115,6 @@ func SetConfigHandle(a ...any) Handle {
|
|||
if ok {
|
||||
pluginFn(h)
|
||||
}
|
||||
reload.Reload()
|
||||
return *h
|
||||
}
|
||||
|
||||
|
|
339
cache/cachemanager/manger.go
vendored
339
cache/cachemanager/manger.go
vendored
|
@ -2,156 +2,82 @@ package cachemanager
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"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"
|
||||
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||
"github.com/fthvgb1/wp-go/safety"
|
||||
"runtime"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var mapFlush = safety.NewMap[string, func(any)]()
|
||||
var anyFlush = safety.NewMap[string, func()]()
|
||||
var mutex sync.Mutex
|
||||
|
||||
var varCache = safety.NewMap[string, any]()
|
||||
var mapCache = safety.NewMap[string, any]()
|
||||
|
||||
func SetVarCache[T any](name string, v *cache.VarCache[T]) error {
|
||||
vv, ok := varCache.Load(name)
|
||||
if !ok {
|
||||
varCache.Store(name, v)
|
||||
return nil
|
||||
}
|
||||
_, ok = vv.(*cache.VarCache[T])
|
||||
if ok {
|
||||
varCache.Store(name, v)
|
||||
return nil
|
||||
}
|
||||
return errors.New(str.Join("cache ", name, " type err"))
|
||||
type Queue struct {
|
||||
Name string
|
||||
Fn func(context.Context)
|
||||
}
|
||||
|
||||
func SetMapCache[K comparable, V any](name string, ca *cache.MapCache[K, V]) error {
|
||||
v, ok := mapCache.Load(name)
|
||||
if !ok {
|
||||
mapCache.Store(name, ca)
|
||||
return nil
|
||||
}
|
||||
_, ok = v.(*cache.MapCache[K, V])
|
||||
if !ok {
|
||||
return errors.New(str.Join("cache ", name, " type err"))
|
||||
}
|
||||
mapCache.Store(name, ca)
|
||||
return nil
|
||||
type Queues []Queue
|
||||
|
||||
func (q *Queues) Get(name string) Queue {
|
||||
_, v := slice.SearchFirst(*q, func(t Queue) bool {
|
||||
return name == t.Name
|
||||
})
|
||||
return v
|
||||
}
|
||||
|
||||
type flush interface {
|
||||
Flush(ctx context.Context)
|
||||
func (q *Queues) Set(name string, fn func(context.Context)) {
|
||||
i := slice.IndexOfBy(*q, func(t Queue) bool {
|
||||
return name == t.Name
|
||||
})
|
||||
if i > -1 {
|
||||
(*q)[i].Fn = fn
|
||||
return
|
||||
}
|
||||
*q = append(*q, Queue{name, fn})
|
||||
}
|
||||
|
||||
func (q *Queues) Del(name string) {
|
||||
i := slice.IndexOfBy(*q, func(t Queue) bool {
|
||||
return name == t.Name
|
||||
})
|
||||
if i > -1 {
|
||||
slice.Delete((*[]Queue)(q), i)
|
||||
}
|
||||
}
|
||||
|
||||
type clearExpired interface {
|
||||
ClearExpired(ctx context.Context)
|
||||
}
|
||||
|
||||
var clears []clearExpired
|
||||
var clears = safety.NewVar(Queues{})
|
||||
|
||||
var flushes []flush
|
||||
var flushes = safety.NewVar(Queues{})
|
||||
|
||||
func Flush() {
|
||||
ctx := context.WithValue(context.Background(), "execFlushBy", "mangerFlushFn")
|
||||
for _, f := range flushes {
|
||||
f.Flush(ctx)
|
||||
for _, f := range flushes.Load() {
|
||||
f.Fn(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
func FlushMapVal[T any](name string, keys ...T) {
|
||||
v, ok := mapFlush.Load(name)
|
||||
if !ok || len(keys) < 1 {
|
||||
return
|
||||
}
|
||||
v(keys)
|
||||
func Flushes(ctx context.Context, names ...string) {
|
||||
execute(ctx, flushes, names...)
|
||||
}
|
||||
|
||||
func FlushAnyVal(name ...string) {
|
||||
for _, s := range name {
|
||||
v, ok := anyFlush.Load(s)
|
||||
if ok {
|
||||
v()
|
||||
func execute(ctx context.Context, q *safety.Var[Queues], names ...string) {
|
||||
queues := q.Load()
|
||||
for _, name := range names {
|
||||
queue := queues.Get(name)
|
||||
if queue.Fn != nil {
|
||||
queue.Fn(ctx)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func PushMangerMap[K comparable, V any](name string, m *cache.MapCache[K, V]) {
|
||||
if name == "" {
|
||||
return
|
||||
}
|
||||
mapCache.Store(name, m)
|
||||
anyFlush.Store(name, func() {
|
||||
ctx := context.WithValue(context.Background(), "ctx", "registerFlush")
|
||||
m.Flush(ctx)
|
||||
})
|
||||
mapFlush.Store(name, func(a any) {
|
||||
k, ok := a.([]K)
|
||||
if ok && len(k) > 0 {
|
||||
ctx := context.WithValue(context.Background(), "ctx", "registerFlush")
|
||||
m.Del(ctx, k...)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func GetBy[T any, K comparable](name string, ct context.Context, key K, timeout time.Duration, params ...any) (r T, err error) {
|
||||
ct = context.WithValue(ct, "getCache", name)
|
||||
ca, err := getMap[K, T](name)
|
||||
if err != nil {
|
||||
return r, err
|
||||
}
|
||||
vv, err := ca.GetCache(ct, key, timeout, params...)
|
||||
if err != nil {
|
||||
return r, err
|
||||
}
|
||||
r = vv
|
||||
return
|
||||
}
|
||||
|
||||
func getMap[K comparable, T any](name string) (*cache.MapCache[K, T], error) {
|
||||
m, ok := mapCache.Load(name)
|
||||
if !ok {
|
||||
return nil, errors.New(str.Join("cache ", name, " doesn't exist"))
|
||||
}
|
||||
vk, ok := m.(*cache.MapCache[K, T])
|
||||
if !ok {
|
||||
return nil, errors.New(str.Join("cache ", name, " type error"))
|
||||
}
|
||||
return vk, nil
|
||||
}
|
||||
func GetBatchBy[T any, K comparable](name string, ct context.Context, key []K, timeout time.Duration, params ...any) (r []T, err error) {
|
||||
ct = context.WithValue(ct, "getCache", name)
|
||||
ca, err := getMap[K, T](name)
|
||||
if err != nil {
|
||||
return r, err
|
||||
}
|
||||
vv, err := ca.GetCacheBatch(ct, key, timeout, params...)
|
||||
if err != nil {
|
||||
return r, err
|
||||
}
|
||||
r = vv
|
||||
return
|
||||
}
|
||||
func GetBatchByToMap[T any, K comparable](name string, ct context.Context, key []K, timeout time.Duration, params ...any) (r map[K]T, err error) {
|
||||
ct = context.WithValue(ct, "getCache", name)
|
||||
ca, err := getMap[K, T](name)
|
||||
if err != nil {
|
||||
return r, err
|
||||
}
|
||||
vv, err := ca.GetBatchToMap(ct, key, timeout, params...)
|
||||
if err != nil {
|
||||
return r, err
|
||||
}
|
||||
r = vv
|
||||
return
|
||||
}
|
||||
|
||||
func parseArgs(args ...any) (string, func() time.Duration) {
|
||||
var name string
|
||||
var fn func() time.Duration
|
||||
|
@ -170,42 +96,6 @@ func parseArgs(args ...any) (string, func() time.Duration) {
|
|||
return name, fn
|
||||
}
|
||||
|
||||
func NewPaginationCache[K comparable, V any](m *cache.MapCache[string, helper.PaginationData[V]], maxNum int,
|
||||
dbFn cache.DbFn[K, V], localFn cache.LocalFn[K, V], dbKeyFn, localKeyFn func(K, ...any) string, fetchNum int, name string, a ...any) *cache.Pagination[K, V] {
|
||||
fn := helper.ParseArgs([]func() int(nil), a...)
|
||||
var ma, fet func() int
|
||||
if len(fn) > 0 {
|
||||
ma = fn[0]
|
||||
if len(fn) > 1 {
|
||||
fet = fn[1]
|
||||
}
|
||||
}
|
||||
if ma == nil {
|
||||
ma = reload.BuildFnVal(str.Join("paginationCache-", name, "-maxNum"), maxNum, nil)
|
||||
}
|
||||
if fet == nil {
|
||||
fet = reload.BuildFnVal(str.Join("paginationCache-", name, "-fetchNum"), fetchNum, nil)
|
||||
}
|
||||
p := cache.NewPagination(m, ma, dbFn, localFn, dbKeyFn, localKeyFn, fet, name)
|
||||
mapCache.Store(name, p)
|
||||
return p
|
||||
}
|
||||
|
||||
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] {
|
||||
inc := helper.ParseArgs((*cache.IncreaseUpdate[K, V])(nil), args...)
|
||||
m := cache.NewMapCache[K, V](data, fn, batchFn, inc, buildLockFn[K](args...), args...)
|
||||
FlushPush(m)
|
||||
ClearPush(m)
|
||||
name, f := parseArgs(args...)
|
||||
if name != "" {
|
||||
PushMangerMap(name, m)
|
||||
}
|
||||
if f != nil && name != "" {
|
||||
SetExpireTime(any(data).(cache.SetTime), name, 0, f)
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
func buildLockFn[K comparable](args ...any) cache.LockFn[K] {
|
||||
lockFn := helper.ParseArgs(cache.LockFn[K](nil), args...)
|
||||
name := helper.ParseArgs("", args...)
|
||||
|
@ -228,20 +118,15 @@ func buildLockFn[K comparable](args ...any) cache.LockFn[K] {
|
|||
} else {
|
||||
lo := cache.NewLocks[K](loFn)
|
||||
lockFn = lo.GetLock
|
||||
FlushPush(lo)
|
||||
PushOrSetFlush(Queue{
|
||||
Name: name,
|
||||
Fn: lo.Flush,
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
return lockFn
|
||||
}
|
||||
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] {
|
||||
|
||||
c := NewMapCache[K, V](cache.NewMemoryMapCache[K, V](func() time.Duration {
|
||||
return expireTime
|
||||
}), batchFn, fn, args...)
|
||||
return c
|
||||
}
|
||||
|
||||
func SetExpireTime(c cache.SetTime, name string, expireTime time.Duration, expireTimeFn func() time.Duration) {
|
||||
if name == "" {
|
||||
|
@ -256,95 +141,55 @@ func ChangeExpireTime(t time.Duration, coverConf bool, name ...string) {
|
|||
reload.SetFnVal(s, t, coverConf)
|
||||
}
|
||||
}
|
||||
|
||||
func FlushPush(f ...flush) {
|
||||
flushes = append(flushes, f...)
|
||||
func pushOrSet(q *safety.Var[Queues], queues ...Queue) {
|
||||
mutex.Lock()
|
||||
defer mutex.Unlock()
|
||||
qu := q.Load()
|
||||
for _, queue := range queues {
|
||||
v := qu.Get(queue.Name)
|
||||
if v.Fn != nil {
|
||||
qu.Set(queue.Name, queue.Fn)
|
||||
} else {
|
||||
qu = append(qu, queue)
|
||||
}
|
||||
}
|
||||
q.Store(qu)
|
||||
}
|
||||
func ClearPush(c ...clearExpired) {
|
||||
clears = append(clears, c...)
|
||||
|
||||
// PushOrSetFlush will execute flush func when call Flush or Flushes
|
||||
func PushOrSetFlush(queues ...Queue) {
|
||||
pushOrSet(flushes, queues...)
|
||||
}
|
||||
|
||||
// PushOrSetClearExpired will execute clearExpired func when call ClearExpired or ClearExpireds
|
||||
func PushOrSetClearExpired(queues ...Queue) {
|
||||
pushOrSet(clears, queues...)
|
||||
}
|
||||
|
||||
func del(q *safety.Var[Queues], 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 _, c := range clears {
|
||||
c.ClearExpired(ctx)
|
||||
for _, queue := range clears.Load() {
|
||||
queue.Fn(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
func NewVarCache[T any](c cache.AnyCache[T], fn func(context.Context, ...any) (T, error), a ...any) *cache.VarCache[T] {
|
||||
inc := helper.ParseArgs((*cache.IncreaseUpdateVar[T])(nil), a...)
|
||||
ref := helper.ParseArgs(cache.RefreshVar[T](nil), a...)
|
||||
v := cache.NewVarCache(c, fn, inc, ref, a...)
|
||||
FlushPush(v)
|
||||
name, _ := parseArgs(a...)
|
||||
if name != "" {
|
||||
varCache.Store(name, v)
|
||||
}
|
||||
cc, ok := any(c).(clearExpired)
|
||||
if ok {
|
||||
ClearPush(cc)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func GetVarVal[T any](name string, ctx context.Context, duration time.Duration, a ...any) (r T, err error) {
|
||||
ctx = context.WithValue(ctx, "getCache", name)
|
||||
ca, ok := GetVarCache[T](name)
|
||||
if !ok {
|
||||
err = errors.New(str.Join("cache ", name, " is not exist"))
|
||||
return
|
||||
}
|
||||
v, err := ca.GetCache(ctx, duration, a...)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
r = v
|
||||
return
|
||||
}
|
||||
|
||||
func NewVarMemoryCache[T any](fn func(context.Context, ...any) (T, error), expired time.Duration, a ...any) *cache.VarCache[T] {
|
||||
c := cache.NewVarMemoryCache[T](nil)
|
||||
name, e := parseArgs(a...)
|
||||
SetExpireTime(c, name, expired, e)
|
||||
v := NewVarCache[T](c, fn, a...)
|
||||
return v
|
||||
}
|
||||
|
||||
func GetVarCache[T any](name string) (*cache.VarCache[T], bool) {
|
||||
v, ok := varCache.Load(name)
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
vv, ok := v.(*cache.VarCache[T])
|
||||
return vv, ok
|
||||
}
|
||||
|
||||
func GetMapCache[K comparable, V any](name string) (*cache.MapCache[K, V], bool) {
|
||||
vv, err := getMap[K, V](name)
|
||||
return vv, err == nil
|
||||
}
|
||||
|
||||
func GetPaginationCache[K comparable, V any](name string) (*cache.Pagination[K, V], bool) {
|
||||
v, err := getPagination[K, V](name)
|
||||
return v, err == nil
|
||||
}
|
||||
|
||||
func Pagination[V any, K comparable](name string, ctx context.Context, timeout time.Duration, k K, page, limit int, a ...any) ([]V, int, error) {
|
||||
v, err := getPagination[K, V](name)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return v.Pagination(ctx, timeout, k, page, limit, a...)
|
||||
}
|
||||
|
||||
func getPagination[K comparable, T any](name string) (*cache.Pagination[K, T], error) {
|
||||
m, ok := mapCache.Load(name)
|
||||
if !ok {
|
||||
return nil, errors.New(str.Join("cache ", name, " doesn't exist"))
|
||||
}
|
||||
vk, ok := m.(*cache.Pagination[K, T])
|
||||
if !ok {
|
||||
return nil, errors.New(str.Join("cache ", name, " type error"))
|
||||
}
|
||||
return vk, nil
|
||||
}
|
||||
|
|
4
cache/cachemanager/manger_test.go
vendored
4
cache/cachemanager/manger_test.go
vendored
|
@ -45,7 +45,7 @@ func TestFlushMapVal(t *testing.T) {
|
|||
}
|
||||
p.Wait()
|
||||
fmt.Println(gets, count)
|
||||
FlushMapVal("test", 3, 4)
|
||||
DelMapCacheVal("test", 3, 4)
|
||||
fmt.Println(vv.Get(ctx, 3))
|
||||
fmt.Println(vv.Get(ctx, 4))
|
||||
get, err := GetBy[int]("test", ctx, 3, time.Second)
|
||||
|
@ -54,7 +54,7 @@ func TestFlushMapVal(t *testing.T) {
|
|||
}
|
||||
fmt.Println(get, count)
|
||||
fmt.Println(vv.Get(ctx, 5))
|
||||
FlushAnyVal("test")
|
||||
Flushes(ctx, "test")
|
||||
fmt.Println(vv.Get(ctx, 5))
|
||||
fmt.Println(vv.Get(ctx, 6))
|
||||
//fmt.Println(GetVarCache("test"))
|
||||
|
|
147
cache/cachemanager/mapcache.go
vendored
Normal file
147
cache/cachemanager/mapcache.go
vendored
Normal file
|
@ -0,0 +1,147 @@
|
|||
package cachemanager
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"github.com/fthvgb1/wp-go/cache"
|
||||
"github.com/fthvgb1/wp-go/helper"
|
||||
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||
"github.com/fthvgb1/wp-go/safety"
|
||||
"time"
|
||||
)
|
||||
|
||||
var mapDelFuncs = safety.NewMap[string, func(any)]()
|
||||
|
||||
var mapCache = safety.NewMap[string, any]()
|
||||
|
||||
func SetMapCache[K comparable, V any](name string, ca *cache.MapCache[K, V]) error {
|
||||
v, ok := mapCache.Load(name)
|
||||
if !ok {
|
||||
mapCache.Store(name, ca)
|
||||
return nil
|
||||
}
|
||||
_, ok = v.(*cache.MapCache[K, V])
|
||||
if !ok {
|
||||
return errors.New(str.Join("cache ", name, " type err"))
|
||||
}
|
||||
mapCache.Store(name, ca)
|
||||
return nil
|
||||
}
|
||||
|
||||
// PushMangerMap will del mapCache val with name When call DelMapCacheVal
|
||||
func PushMangerMap[K comparable, V any](name string, m *cache.MapCache[K, V]) {
|
||||
if name == "" {
|
||||
return
|
||||
}
|
||||
mapCache.Store(name, m)
|
||||
mapDelFuncs.Store(name, func(a any) {
|
||||
k, ok := a.([]K)
|
||||
if ok && len(k) > 0 {
|
||||
mm, ok := mapCache.Load(name)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
c, ok := mm.(*cache.MapCache[K, V])
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
ctx := context.WithValue(context.Background(), "ctx", "registerFlush")
|
||||
c.Del(ctx, k...)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func GetBy[T any, K comparable](name string, ct context.Context, key K, timeout time.Duration, params ...any) (r T, err error) {
|
||||
ct = context.WithValue(ct, "getCache", name)
|
||||
ca, err := getMap[K, T](name)
|
||||
if err != nil {
|
||||
return r, err
|
||||
}
|
||||
vv, err := ca.GetCache(ct, key, timeout, params...)
|
||||
if err != nil {
|
||||
return r, err
|
||||
}
|
||||
r = vv
|
||||
return
|
||||
}
|
||||
|
||||
func getMap[K comparable, T any](name string) (*cache.MapCache[K, T], error) {
|
||||
m, ok := mapCache.Load(name)
|
||||
if !ok {
|
||||
return nil, errors.New(str.Join("cache ", name, " doesn't exist"))
|
||||
}
|
||||
vk, ok := m.(*cache.MapCache[K, T])
|
||||
if !ok {
|
||||
return nil, errors.New(str.Join("cache ", name, " type error"))
|
||||
}
|
||||
return vk, nil
|
||||
}
|
||||
func GetBatchBy[T any, K comparable](name string, ct context.Context, key []K, timeout time.Duration, params ...any) (r []T, err error) {
|
||||
ct = context.WithValue(ct, "getCache", name)
|
||||
ca, err := getMap[K, T](name)
|
||||
if err != nil {
|
||||
return r, err
|
||||
}
|
||||
vv, err := ca.GetCacheBatch(ct, key, timeout, params...)
|
||||
if err != nil {
|
||||
return r, err
|
||||
}
|
||||
r = vv
|
||||
return
|
||||
}
|
||||
func GetBatchByToMap[T any, K comparable](name string, ct context.Context, key []K, timeout time.Duration, params ...any) (r map[K]T, err error) {
|
||||
ct = context.WithValue(ct, "getCache", name)
|
||||
ca, err := getMap[K, T](name)
|
||||
if err != nil {
|
||||
return r, err
|
||||
}
|
||||
vv, err := ca.GetBatchToMap(ct, key, timeout, params...)
|
||||
if err != nil {
|
||||
return r, err
|
||||
}
|
||||
r = vv
|
||||
return
|
||||
}
|
||||
|
||||
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] {
|
||||
inc := helper.ParseArgs((*cache.IncreaseUpdate[K, V])(nil), args...)
|
||||
m := cache.NewMapCache[K, V](data, fn, batchFn, inc, buildLockFn[K](args...), args...)
|
||||
name, f := parseArgs(args...)
|
||||
if name != "" {
|
||||
PushMangerMap(name, m)
|
||||
}
|
||||
PushOrSetFlush(Queue{
|
||||
Name: name,
|
||||
Fn: m.Flush,
|
||||
})
|
||||
PushOrSetClearExpired(Queue{
|
||||
Name: name,
|
||||
Fn: m.ClearExpired,
|
||||
})
|
||||
if f != nil && name != "" {
|
||||
SetExpireTime(any(data).(cache.SetTime), name, 0, f)
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
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] {
|
||||
|
||||
c := NewMapCache[K, V](cache.NewMemoryMapCache[K, V](func() time.Duration {
|
||||
return expireTime
|
||||
}), batchFn, fn, args...)
|
||||
return c
|
||||
}
|
||||
|
||||
func GetMapCache[K comparable, V any](name string) (*cache.MapCache[K, V], bool) {
|
||||
vv, err := getMap[K, V](name)
|
||||
return vv, err == nil
|
||||
}
|
||||
|
||||
func DelMapCacheVal[T any](name string, keys ...T) {
|
||||
v, ok := mapDelFuncs.Load(name)
|
||||
if !ok || len(keys) < 1 {
|
||||
return
|
||||
}
|
||||
v(keys)
|
||||
}
|
57
cache/cachemanager/pagination.go
vendored
Normal file
57
cache/cachemanager/pagination.go
vendored
Normal file
|
@ -0,0 +1,57 @@
|
|||
package cachemanager
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"github.com/fthvgb1/wp-go/cache"
|
||||
"github.com/fthvgb1/wp-go/cache/reload"
|
||||
"github.com/fthvgb1/wp-go/helper"
|
||||
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func NewPaginationCache[K comparable, V any](m *cache.MapCache[string, helper.PaginationData[V]], maxNum int,
|
||||
dbFn cache.DbFn[K, V], localFn cache.LocalFn[K, V], dbKeyFn, localKeyFn func(K, ...any) string, fetchNum int, name string, a ...any) *cache.Pagination[K, V] {
|
||||
fn := helper.ParseArgs([]func() int(nil), a...)
|
||||
var ma, fet func() int
|
||||
if len(fn) > 0 {
|
||||
ma = fn[0]
|
||||
if len(fn) > 1 {
|
||||
fet = fn[1]
|
||||
}
|
||||
}
|
||||
if ma == nil {
|
||||
ma = reload.BuildFnVal(str.Join("paginationCache-", name, "-maxNum"), maxNum, nil)
|
||||
}
|
||||
if fet == nil {
|
||||
fet = reload.BuildFnVal(str.Join("paginationCache-", name, "-fetchNum"), fetchNum, nil)
|
||||
}
|
||||
p := cache.NewPagination(m, ma, dbFn, localFn, dbKeyFn, localKeyFn, fet, name)
|
||||
mapCache.Store(name, p)
|
||||
return p
|
||||
}
|
||||
|
||||
func GetPaginationCache[K comparable, V any](name string) (*cache.Pagination[K, V], bool) {
|
||||
v, err := getPagination[K, V](name)
|
||||
return v, err == nil
|
||||
}
|
||||
|
||||
func Pagination[V any, K comparable](name string, ctx context.Context, timeout time.Duration, k K, page, limit int, a ...any) ([]V, int, error) {
|
||||
v, err := getPagination[K, V](name)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return v.Pagination(ctx, timeout, k, page, limit, a...)
|
||||
}
|
||||
|
||||
func getPagination[K comparable, T any](name string) (*cache.Pagination[K, T], error) {
|
||||
m, ok := mapCache.Load(name)
|
||||
if !ok {
|
||||
return nil, errors.New(str.Join("cache ", name, " doesn't exist"))
|
||||
}
|
||||
vk, ok := m.(*cache.Pagination[K, T])
|
||||
if !ok {
|
||||
return nil, errors.New(str.Join("cache ", name, " type error"))
|
||||
}
|
||||
return vk, nil
|
||||
}
|
82
cache/cachemanager/varcache.go
vendored
Normal file
82
cache/cachemanager/varcache.go
vendored
Normal file
|
@ -0,0 +1,82 @@
|
|||
package cachemanager
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"github.com/fthvgb1/wp-go/cache"
|
||||
"github.com/fthvgb1/wp-go/helper"
|
||||
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||
"github.com/fthvgb1/wp-go/safety"
|
||||
"time"
|
||||
)
|
||||
|
||||
var varCache = safety.NewMap[string, any]()
|
||||
|
||||
func SetVarCache[T any](name string, v *cache.VarCache[T]) error {
|
||||
vv, ok := varCache.Load(name)
|
||||
if !ok {
|
||||
varCache.Store(name, v)
|
||||
return nil
|
||||
}
|
||||
_, ok = vv.(*cache.VarCache[T])
|
||||
if ok {
|
||||
varCache.Store(name, v)
|
||||
return nil
|
||||
}
|
||||
return errors.New(str.Join("cache ", name, " type err"))
|
||||
}
|
||||
|
||||
func NewVarCache[T any](c cache.AnyCache[T], fn func(context.Context, ...any) (T, error), a ...any) *cache.VarCache[T] {
|
||||
inc := helper.ParseArgs((*cache.IncreaseUpdateVar[T])(nil), a...)
|
||||
ref := helper.ParseArgs(cache.RefreshVar[T](nil), a...)
|
||||
v := cache.NewVarCache(c, fn, inc, ref, a...)
|
||||
|
||||
name, _ := parseArgs(a...)
|
||||
if name != "" {
|
||||
varCache.Store(name, v)
|
||||
}
|
||||
PushOrSetFlush(Queue{
|
||||
Name: name,
|
||||
Fn: v.Flush,
|
||||
})
|
||||
cc, ok := any(c).(clearExpired)
|
||||
if ok {
|
||||
PushOrSetClearExpired(Queue{
|
||||
Name: name,
|
||||
Fn: cc.ClearExpired,
|
||||
})
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func GetVarVal[T any](name string, ctx context.Context, duration time.Duration, a ...any) (r T, err error) {
|
||||
ctx = context.WithValue(ctx, "getCache", name)
|
||||
ca, ok := GetVarCache[T](name)
|
||||
if !ok {
|
||||
err = errors.New(str.Join("cache ", name, " is not exist"))
|
||||
return
|
||||
}
|
||||
v, err := ca.GetCache(ctx, duration, a...)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
r = v
|
||||
return
|
||||
}
|
||||
|
||||
func NewVarMemoryCache[T any](fn func(context.Context, ...any) (T, error), expired time.Duration, a ...any) *cache.VarCache[T] {
|
||||
c := cache.NewVarMemoryCache[T](nil)
|
||||
name, e := parseArgs(a...)
|
||||
SetExpireTime(c, name, expired, e)
|
||||
v := NewVarCache[T](c, fn, a...)
|
||||
return v
|
||||
}
|
||||
|
||||
func GetVarCache[T any](name string) (*cache.VarCache[T], bool) {
|
||||
v, ok := varCache.Load(name)
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
vv, ok := v.(*cache.VarCache[T])
|
||||
return vv, ok
|
||||
}
|
|
@ -298,6 +298,15 @@ func IndexOf[T comparable](a []T, v T) int {
|
|||
}
|
||||
return -1
|
||||
}
|
||||
func IndexOfBy[T any](a []T, fn func(T) bool) int {
|
||||
for i, t := range a {
|
||||
ok := fn(t)
|
||||
if ok {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
func ForEach[T any](a []T, fn func(i int, v T)) {
|
||||
for i, t := range a {
|
||||
|
|
Loading…
Reference in New Issue
Block a user