2023-12-11 14:32:00 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"github.com/fthvgb1/wp-go/app/pkg/config"
|
|
|
|
"github.com/fthvgb1/wp-go/app/pkg/dao"
|
2024-04-15 07:25:19 +00:00
|
|
|
"github.com/fthvgb1/wp-go/app/pkg/logs"
|
2023-12-11 14:32:00 +00:00
|
|
|
"github.com/fthvgb1/wp-go/app/theme/wp"
|
|
|
|
"github.com/fthvgb1/wp-go/cache/cachemanager"
|
2024-04-14 14:49:40 +00:00
|
|
|
"github.com/fthvgb1/wp-go/cache/reload"
|
2023-12-11 14:32:00 +00:00
|
|
|
"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"
|
2024-04-15 07:25:19 +00:00
|
|
|
str "strings"
|
2023-12-11 14:32:00 +00:00
|
|
|
"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) {
|
2024-04-15 07:25:19 +00:00
|
|
|
fmt.Println("flush redis cache")
|
2023-12-11 14:32:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
2024-04-15 07:25:19 +00:00
|
|
|
fmt.Println("clear expired redis cache")
|
2023-12-11 14:32:00 +00:00
|
|
|
}
|
2024-04-15 07:25:19 +00:00
|
|
|
|
|
|
|
// 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) {
|
2023-12-11 14:32:00 +00:00
|
|
|
vv, ok := cachemanager.GetMapCache[string, dao.PostIds]("listPostIds")
|
|
|
|
if ok {
|
|
|
|
_, ok := any(vv.Cache).(*RdmCache[string, dao.PostIds])
|
|
|
|
if ok {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
2024-04-14 14:49:40 +00:00
|
|
|
reload.AppendOnceFn(func() {
|
2024-04-15 07:25:19 +00:00
|
|
|
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")
|
|
|
|
}
|
|
|
|
})
|
2023-12-11 14:32:00 +00:00
|
|
|
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{
|
2024-04-15 07:25:19 +00:00
|
|
|
Ids: slice.Map(str.Split(m["ids"], ","), strings.ToInt[uint64]),
|
2023-12-11 14:32:00 +00:00
|
|
|
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{
|
2024-04-15 07:25:19 +00:00
|
|
|
"ids": str.Join(t, ","),
|
2023-12-11 14:32:00 +00:00
|
|
|
"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")
|
|
|
|
}
|