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") }