wp-go/app/plugins/devexample/plugintt/redisCache.go.dev

142 lines
3.8 KiB
Plaintext

package main
import (
"context"
"errors"
"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"
"github.com/fthvgb1/wp-go/helper/number"
"github.com/fthvgb1/wp-go/helper/slice"
"github.com/fthvgb1/wp-go/helper/strings"
"github.com/redis/go-redis/v9"
"strconv"
str "strings"
"time"
)
type RdmCache[K comparable, V any] struct {
expired func() time.Duration
rdb *redis.Client
keyFn func(K) string
name string
resFn func(map[string]string) V
saveData func(V) map[string]string
}
func (r *RdmCache[K, V]) SetExpiredTime(f func() time.Duration) {
r.expired = f
}
func (r *RdmCache[K, V]) Get(ctx context.Context, key K) (V, bool) {
var re V
result, err := r.rdb.Exists(ctx, r.keyFn(key)).Result()
if result <= 0 || err != nil {
return re, false
}
rr, err := r.rdb.HGetAll(ctx, r.keyFn(key)).Result()
if errors.Is(err, redis.Nil) {
return re, false
}
if err != nil {
return re, false
}
return r.resFn(rr), true
}
func (r *RdmCache[K, V]) Set(ctx context.Context, key K, val V) {
k := r.keyFn(key)
result, err := r.rdb.HSet(ctx, k, r.saveData(val)).Result()
b, err := r.rdb.Expire(ctx, k, r.expired()).Result()
if err != nil {
fmt.Println(result, b, err)
return
}
fmt.Println(result, err)
}
func (r *RdmCache[K, V]) GetExpireTime(ctx context.Context) time.Duration {
return r.expired()
}
func (r *RdmCache[K, V]) Ttl(ctx context.Context, key K) time.Duration {
result, err := r.rdb.TTL(ctx, r.keyFn(key)).Result()
if err != nil {
return 0
}
return result
}
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) {
r.rdb.Del(ctx, slice.Map(key, r.keyFn)...)
}
func (r *RdmCache[K, V]) ClearExpired(ctx context.Context) {
fmt.Println("clear expired redis cache")
}
// 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])
if ok {
return
}
}
reload.AppendOnceFn(func() {
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",
Password: "", // no password set
DB: 0, // use default DB
})
r := RdmCache[string, dao.PostIds]{
expired: func() time.Duration {
return time.Minute
},
keyFn: func(u string) string {
return strings.Join("postIds:", u)
},
rdb: rdm,
name: "",
resFn: func(m map[string]string) dao.PostIds {
return dao.PostIds{
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": str.Join(t, ","),
"length": strconv.Itoa(ids.Length),
}
},
}
cachemanager.NewMapCache[string, dao.PostIds](&r, nil, dao.SearchPostIds, config.GetConfig().CacheTime.PostListCacheTime, "listPostIds", func() time.Duration {
return config.GetConfig().CacheTime.PostListCacheTime
})
fmt.Println("redis cache inited ok")
}