fix(redis): 修复缓存设置和清除逻辑的问题
All checks were successful
Build docker and publish / build (20.15.1) (push) Successful in 7m20s

修复Redis缓存设置未设置TTL的问题,使用节点拉取间隔加60秒作为TTL
修复ClearServerAllCache中重复添加keys的问题
修复ClearServerCache中未使用cursor参数的问题
优化ClearServerAllCache以支持清除多种前缀的缓存
This commit is contained in:
shanshanzhong 2025-11-23 23:39:30 -08:00
parent 58107ed76f
commit 4ad384b01a
4 changed files with 57 additions and 50 deletions

View File

@ -1,25 +1,25 @@
package user package user
import ( import (
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
logic "github.com/perfect-panel/server/internal/logic/public/user" logic "github.com/perfect-panel/server/internal/logic/public/user"
"github.com/perfect-panel/server/internal/svc" "github.com/perfect-panel/server/internal/svc"
"github.com/perfect-panel/server/internal/types" "github.com/perfect-panel/server/internal/types"
"github.com/perfect-panel/server/pkg/result" "github.com/perfect-panel/server/pkg/result"
) )
func BindInviteCodeHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) { func BindInviteCodeHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
return func(c *gin.Context) { return func(c *gin.Context) {
var req types.BindInviteCodeRequest var req types.BindInviteCodeRequest
_ = c.ShouldBind(&req) _ = c.ShouldBind(&req)
validateErr := svcCtx.Validate(&req) validateErr := svcCtx.Validate(&req)
if validateErr != nil { if validateErr != nil {
result.ParamErrorResult(c, validateErr) result.ParamErrorResult(c, validateErr)
return return
} }
l := logic.NewBindInviteCodeLogic(c.Request.Context(), svcCtx) l := logic.NewBindInviteCodeLogic(c.Request.Context(), svcCtx)
err := l.BindInviteCode(&req) err := l.BindInviteCode(&req)
result.HttpResult(c, nil, err) result.HttpResult(c, nil, err)
} }
} }

View File

@ -4,6 +4,7 @@ import (
"encoding/base64" "encoding/base64"
"encoding/json" "encoding/json"
"fmt" "fmt"
"time"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/perfect-panel/server/internal/model/node" "github.com/perfect-panel/server/internal/model/node"
@ -90,7 +91,8 @@ func (l *GetServerConfigLogic) GetServerConfig(req *types.GetServerConfigRequest
} }
etag := tool.GenerateETag(c) etag := tool.GenerateETag(c)
l.ctx.Header("ETag", etag) l.ctx.Header("ETag", etag)
if err = l.svcCtx.Redis.Set(l.ctx, cacheKey, c, -1).Err(); err != nil { ttl := time.Second * time.Duration(l.svcCtx.Config.Node.NodePullInterval+60)
if err = l.svcCtx.Redis.Set(l.ctx, cacheKey, c, ttl).Err(); err != nil {
l.Errorw("[GetServerConfig] redis set error", logger.Field("error", err.Error())) l.Errorw("[GetServerConfig] redis set error", logger.Field("error", err.Error()))
} }
// Check If-None-Match header // Check If-None-Match header

View File

@ -4,6 +4,7 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"strings" "strings"
"time"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/perfect-panel/server/internal/model/node" "github.com/perfect-panel/server/internal/model/node"
@ -121,10 +122,11 @@ func (l *GetServerUserListLogic) GetServerUserList(req *types.GetServerUserListR
val, _ := json.Marshal(resp) val, _ := json.Marshal(resp)
etag := tool.GenerateETag(val) etag := tool.GenerateETag(val)
l.ctx.Header("ETag", etag) l.ctx.Header("ETag", etag)
err = l.svcCtx.Redis.Set(l.ctx, cacheKey, string(val), -1).Err() ttl := time.Second * time.Duration(l.svcCtx.Config.Node.NodePullInterval+60)
if err != nil { err = l.svcCtx.Redis.Set(l.ctx, cacheKey, string(val), ttl).Err()
l.Errorw("[ServerUserListCacheKey] redis set error", logger.Field("error", err.Error())) if err != nil {
} l.Errorw("[ServerUserListCacheKey] redis set error", logger.Field("error", err.Error()))
}
// Check If-None-Match header // Check If-None-Match header
if match := l.ctx.GetHeader("If-None-Match"); match == etag { if match := l.ctx.GetHeader("If-None-Match"); match == etag {
return nil, xerr.StatusNotModified return nil, xerr.StatusNotModified

View File

@ -130,7 +130,7 @@ func (m *customServerModel) ClearNodeCache(ctx context.Context, params *FilterNo
return err return err
} }
if len(keys) > 0 { if len(keys) > 0 {
cacheKeys = append(keys, keys...) cacheKeys = append(cacheKeys, keys...)
} }
cursor = newCursor cursor = newCursor
if cursor == 0 { if cursor == 0 {
@ -152,11 +152,11 @@ func (m *customServerModel) ClearServerCache(ctx context.Context, serverId int64
var cacheKeys []string var cacheKeys []string
cacheKeys = append(cacheKeys, fmt.Sprintf("%s%d", ServerUserListCacheKey, serverId)) cacheKeys = append(cacheKeys, fmt.Sprintf("%s%d", ServerUserListCacheKey, serverId))
var cursor uint64 var cursor uint64
for { for {
keys, newCursor, err := m.Cache.Scan(ctx, 0, fmt.Sprintf("%s%d*", ServerConfigCacheKey, serverId), 100).Result() keys, newCursor, err := m.Cache.Scan(ctx, cursor, fmt.Sprintf("%s%d*", ServerConfigCacheKey, serverId), 100).Result()
if err != nil { if err != nil {
return err return err
} }
if len(keys) > 0 { if len(keys) > 0 {
cacheKeys = append(cacheKeys, keys...) cacheKeys = append(cacheKeys, keys...)
} }
@ -174,27 +174,30 @@ func (m *customServerModel) ClearServerCache(ctx context.Context, serverId int64
} }
func (m *customServerModel) ClearServerAllCache(ctx context.Context) error { func (m *customServerModel) ClearServerAllCache(ctx context.Context) error {
var cursor uint64 var cursor uint64
var keys []string var keys []string
prefix := ServerConfigCacheKey + "*" prefixes := []string{ServerConfigCacheKey + "*", ServerUserListCacheKey + "*"}
for { for _, prefix := range prefixes {
scanKeys, newCursor, err := m.Cache.Scan(ctx, cursor, prefix, 999).Result() cursor = 0
if err != nil { for {
m.Logger.Error(ctx, fmt.Sprintf("ClearServerAllCache err:%v", err)) scanKeys, newCursor, err := m.Cache.Scan(ctx, cursor, prefix, 999).Result()
break if err != nil {
} m.Logger.Error(ctx, fmt.Sprintf("ClearServerAllCache err:%v", err))
m.Logger.Info(ctx, fmt.Sprintf("ClearServerAllCache query keys:%v", scanKeys)) break
keys = append(keys, scanKeys...) }
cursor = newCursor m.Logger.Info(ctx, fmt.Sprintf("ClearServerAllCache query keys:%v", scanKeys))
if cursor == 0 { keys = append(keys, scanKeys...)
break cursor = newCursor
} if cursor == 0 {
} break
if len(keys) > 0 { }
m.Logger.Info(ctx, fmt.Sprintf("ClearServerAllCache keys:%v", keys)) }
return m.Cache.Del(ctx, keys...).Err() }
} if len(keys) > 0 {
return nil m.Logger.Info(ctx, fmt.Sprintf("ClearServerAllCache keys:%v", keys))
return m.Cache.Del(ctx, keys...).Err()
}
return nil
} }
// InSet 支持多值 OR 查询 // InSet 支持多值 OR 查询