fix: 修复手动触发去重TTL和日限制次数,优化权限检查和错误日志
This commit is contained in:
@@ -53,9 +53,13 @@ func (s *ManualTriggerService) TriggerSingle(ctx context.Context, cardID uint, t
|
||||
// 检查每日触发限制
|
||||
todayCount, err := s.logStore.CountTodayTriggers(ctx, triggeredBy)
|
||||
if err != nil {
|
||||
s.logger.Error("查询今日触发次数失败",
|
||||
zap.Uint("triggered_by", triggeredBy),
|
||||
zap.String("task_type", taskType),
|
||||
zap.Error(err))
|
||||
return err
|
||||
}
|
||||
if todayCount >= 100 { // 每日最多触发100次
|
||||
if todayCount >= 500 { // 每日最多触发500次
|
||||
return errors.New(errors.CodeInvalidParam, "已达到每日触发次数上限")
|
||||
}
|
||||
|
||||
@@ -63,13 +67,17 @@ func (s *ManualTriggerService) TriggerSingle(ctx context.Context, cardID uint, t
|
||||
dedupeKey := constants.RedisPollingManualDedupeKey(taskType)
|
||||
added, err := s.redis.SAdd(ctx, dedupeKey, cardID).Result()
|
||||
if err != nil {
|
||||
s.logger.Error("Redis去重操作失败",
|
||||
zap.Uint("card_id", cardID),
|
||||
zap.String("task_type", taskType),
|
||||
zap.Error(err))
|
||||
return err
|
||||
}
|
||||
if added == 0 {
|
||||
return errors.New(errors.CodeInvalidParam, "该卡已在手动触发队列中")
|
||||
}
|
||||
// 设置去重 key 过期时间(1小时)
|
||||
s.redis.Expire(ctx, dedupeKey, time.Hour)
|
||||
// 设置去重 key 过期时间(24小时,与日限制周期对齐)
|
||||
s.redis.Expire(ctx, dedupeKey, 24*time.Hour)
|
||||
|
||||
// 创建触发日志
|
||||
cardIDsJSON, _ := json.Marshal([]uint{cardID})
|
||||
@@ -83,12 +91,20 @@ func (s *ManualTriggerService) TriggerSingle(ctx context.Context, cardID uint, t
|
||||
TriggeredAt: time.Now(),
|
||||
}
|
||||
if err := s.logStore.Create(ctx, triggerLog); err != nil {
|
||||
s.logger.Error("创建触发日志失败",
|
||||
zap.Uint("card_id", cardID),
|
||||
zap.Uint("triggered_by", triggeredBy),
|
||||
zap.Error(err))
|
||||
return err
|
||||
}
|
||||
|
||||
// 加入手动触发队列(使用 List,优先级高于定时轮询)
|
||||
queueKey := constants.RedisPollingManualQueueKey(taskType)
|
||||
if err := s.redis.LPush(ctx, queueKey, cardID).Err(); err != nil {
|
||||
s.logger.Error("写入手动触发队列失败",
|
||||
zap.Uint("card_id", cardID),
|
||||
zap.String("task_type", taskType),
|
||||
zap.Error(err))
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -126,7 +142,7 @@ func (s *ManualTriggerService) TriggerBatch(ctx context.Context, cardIDs []uint,
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if todayCount >= 100 {
|
||||
if todayCount >= 500 { // 每日最多触发500次
|
||||
return nil, errors.New(errors.CodeInvalidParam, "已达到每日触发次数上限")
|
||||
}
|
||||
|
||||
@@ -188,8 +204,8 @@ func (s *ManualTriggerService) processBatchTrigger(ctx context.Context, logID ui
|
||||
}
|
||||
}
|
||||
|
||||
// 设置去重 key 过期时间
|
||||
s.redis.Expire(ctx, dedupeKey, time.Hour)
|
||||
// 设置去重 key 过期时间(24小时,与日限制周期对齐)
|
||||
s.redis.Expire(ctx, dedupeKey, 24*time.Hour)
|
||||
|
||||
// 更新最终状态
|
||||
_ = s.logStore.UpdateProgress(ctx, logID, processedCount, successCount, failedCount)
|
||||
@@ -235,7 +251,7 @@ func (s *ManualTriggerService) TriggerByCondition(ctx context.Context, filter *C
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if todayCount >= 100 {
|
||||
if todayCount >= 500 { // 每日最多触发500次
|
||||
return nil, errors.New(errors.CodeInvalidParam, "已达到每日触发次数上限")
|
||||
}
|
||||
|
||||
@@ -357,18 +373,26 @@ func isValidTaskType(taskType string) bool {
|
||||
}
|
||||
}
|
||||
|
||||
// checkUserTypePermission 检查用户类型是否有手动触发权限
|
||||
// 返回 skip=true 表示超级管理员/平台用户直接放行
|
||||
// 返回 err!=nil 表示企业账号无权限
|
||||
// 返回 skip=false, err=nil 表示代理账号需继续细粒度检查
|
||||
func (s *ManualTriggerService) checkUserTypePermission(ctx context.Context) (skip bool, err error) {
|
||||
userType := middleware.GetUserTypeFromContext(ctx)
|
||||
if userType == constants.UserTypeSuperAdmin || userType == constants.UserTypePlatform {
|
||||
return true, nil
|
||||
}
|
||||
if userType == constants.UserTypeEnterprise {
|
||||
return false, errors.New(errors.CodeForbidden, "企业账号无权限手动触发轮询")
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// canManageCard 检查用户是否有权管理单张卡
|
||||
func (s *ManualTriggerService) canManageCard(ctx context.Context, cardID uint) error {
|
||||
userType := middleware.GetUserTypeFromContext(ctx)
|
||||
|
||||
// 超级管理员和平台用户跳过权限检查
|
||||
if userType == constants.UserTypeSuperAdmin || userType == constants.UserTypePlatform {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 企业账号禁止手动触发
|
||||
if userType == constants.UserTypeEnterprise {
|
||||
return errors.New(errors.CodeForbidden, "企业账号无权限手动触发轮询")
|
||||
skip, err := s.checkUserTypePermission(ctx)
|
||||
if err != nil || skip {
|
||||
return err
|
||||
}
|
||||
|
||||
// 代理账号只能管理自己店铺及下级店铺的卡
|
||||
@@ -388,16 +412,9 @@ func (s *ManualTriggerService) canManageCard(ctx context.Context, cardID uint) e
|
||||
|
||||
// canManageCards 检查用户是否有权管理多张卡
|
||||
func (s *ManualTriggerService) canManageCards(ctx context.Context, cardIDs []uint) error {
|
||||
userType := middleware.GetUserTypeFromContext(ctx)
|
||||
|
||||
// 超级管理员和平台用户跳过权限检查
|
||||
if userType == constants.UserTypeSuperAdmin || userType == constants.UserTypePlatform {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 企业账号禁止手动触发
|
||||
if userType == constants.UserTypeEnterprise {
|
||||
return errors.New(errors.CodeForbidden, "企业账号无权限手动触发轮询")
|
||||
skip, err := s.checkUserTypePermission(ctx)
|
||||
if err != nil || skip {
|
||||
return err
|
||||
}
|
||||
|
||||
// 从 Context 获取预计算的下级店铺 ID 列表
|
||||
@@ -434,16 +451,9 @@ func (s *ManualTriggerService) canManageCards(ctx context.Context, cardIDs []uin
|
||||
|
||||
// applyShopPermissionFilter 应用店铺权限过滤(代理只能筛选自己管理的卡)
|
||||
func (s *ManualTriggerService) applyShopPermissionFilter(ctx context.Context, filter *ConditionFilter) error {
|
||||
userType := middleware.GetUserTypeFromContext(ctx)
|
||||
|
||||
// 超级管理员和平台用户不需要限制
|
||||
if userType == constants.UserTypeSuperAdmin || userType == constants.UserTypePlatform {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 企业账号禁止手动触发
|
||||
if userType == constants.UserTypeEnterprise {
|
||||
return errors.New(errors.CodeForbidden, "企业账号无权限手动触发轮询")
|
||||
skip, err := s.checkUserTypePermission(ctx)
|
||||
if err != nil || skip {
|
||||
return err
|
||||
}
|
||||
|
||||
// 代理账号:限制只能查询自己店铺及下级店铺的卡
|
||||
|
||||
@@ -270,7 +270,7 @@ func RedisPollingManualQueueKey(taskType string) string {
|
||||
|
||||
// RedisPollingManualDedupeKey 生成手动触发去重的 Redis 键
|
||||
// 用途:Set 存储已加入手动触发队列的卡 ID(用于去重)
|
||||
// 过期时间:1小时
|
||||
// 过期时间:24小时(与日限制周期对齐)
|
||||
func RedisPollingManualDedupeKey(taskType string) string {
|
||||
return fmt.Sprintf("polling:manual:dedupe:%s", taskType)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user