bugfix
This commit is contained in:
+24
-10
@@ -2,6 +2,7 @@ package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
|
||||
"git.lzcwy.cn/zhengchiliu/zt-closet-backend/global"
|
||||
"git.lzcwy.cn/zhengchiliu/zt-closet-backend/internal/dto"
|
||||
@@ -100,6 +101,11 @@ func (s *CollectService) List(ctx context.Context, userID int64, request *dto.Co
|
||||
// 穿搭可能已删除,跳过。
|
||||
continue
|
||||
}
|
||||
// 越权防护(纵深防御):DAO 已按可见性联表过滤,此处再挡一次查询与读取之间
|
||||
// 发生的「转私密 / 被封禁 / 审核驳回」变更,避免下发他人非公开穿搭内容。
|
||||
if outfit.UserID != userID && !isOutfitPublicVisible(outfit) {
|
||||
continue
|
||||
}
|
||||
outfitItems, uerr := s.itemResponses(ctx, outfit.ID)
|
||||
if uerr != nil {
|
||||
continue
|
||||
@@ -133,19 +139,27 @@ func (s *CollectService) GetByTarget(ctx context.Context, userID int64, request
|
||||
}
|
||||
targetID := outfit.ID
|
||||
|
||||
// 是否已收藏:Redis 优先,回落 MySQL。
|
||||
isCollected, err := redisdao.CollectIsMember(ctx, CollectTypeOutfit, targetID, userID)
|
||||
if err != nil {
|
||||
if rec, derr := s.collectDao.CollectGetByTargetAndUser(ctx, CollectTypeOutfit, targetID, userID); derr == nil {
|
||||
isCollected = rec.Status == InteractStatusOn
|
||||
// 是否已收藏:以 MySQL 为权威。
|
||||
// Redis 集合带 TTL,过期后会被后续写入重建为「仅含新成员」,导致 SIsMember/SCard 长期低估,
|
||||
// 因此只在 DB 异常时用 Redis 兜底(降级可用性优先于精确性)。
|
||||
isCollected := false
|
||||
if rec, derr := s.collectDao.CollectGetByTargetAndUser(ctx, CollectTypeOutfit, targetID, userID); derr == nil {
|
||||
isCollected = rec.Status == InteractStatusOn
|
||||
} else if !isNotFound(derr) {
|
||||
slog.WarnContext(ctx, "query collect record failed, fallback to redis",
|
||||
"target_id", targetID, "user_id", userID, "error", derr)
|
||||
if v, rerr := redisdao.CollectIsMember(ctx, CollectTypeOutfit, targetID, userID); rerr == nil {
|
||||
isCollected = v
|
||||
}
|
||||
}
|
||||
|
||||
// 收藏总数:Redis 优先,回落 MySQL。
|
||||
count, err := redisdao.CollectCount(ctx, CollectTypeOutfit, targetID)
|
||||
if err != nil || count == 0 {
|
||||
if dbCnt, derr := s.collectDao.CollectCountByTarget(ctx, CollectTypeOutfit, targetID); derr == nil {
|
||||
count = dbCnt
|
||||
// 收藏总数:以 MySQL 为权威(同上,Redis 仅在 DB 异常时兜底)。
|
||||
count, derr := s.collectDao.CollectCountByTarget(ctx, CollectTypeOutfit, targetID)
|
||||
if derr != nil {
|
||||
slog.WarnContext(ctx, "count collect failed, fallback to redis",
|
||||
"target_id", targetID, "error", derr)
|
||||
if rcnt, rerr := redisdao.CollectCount(ctx, CollectTypeOutfit, targetID); rerr == nil {
|
||||
count = rcnt
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user