package weekstar import ( "context" "net/http" "strconv" "strings" "time" "github.com/redis/go-redis/v9" ) const weekStarRewardRetryPendingTTL = 30 * time.Minute // enqueueRewardRetryTask 把失败发奖记录投递到 Redis Stream,交给 chatapp-cron 执行真正补发。 func (s *WeekStarService) enqueueRewardRetryTask(ctx context.Context, recordID int64) error { streamKey := strings.TrimSpace(s.cfg.WeekStar.RetryStreamKey) if streamKey == "" { return NewAppError(http.StatusInternalServerError, "retry_stream_not_configured", "week star retry stream is not configured") } pendingKey := s.rewardRetryPendingKey(recordID) acquired, err := s.repo.Redis.SetNX(ctx, pendingKey, "1", weekStarRewardRetryPendingTTL).Result() if err != nil { return err } if !acquired { // 已经存在待处理补发任务时直接视为幂等成功,避免重复投递。 return nil } _, err = s.repo.Redis.XAdd(ctx, &redis.XAddArgs{ Stream: streamKey, Values: map[string]any{ "recordId": recordID, }, }).Result() if err != nil { _, _ = s.repo.Redis.Del(context.Background(), pendingKey).Result() return err } return nil } // rewardRetryPendingKey 返回补发任务去重 key,避免同一条记录被重复提交。 func (s *WeekStarService) rewardRetryPendingKey(recordID int64) string { return strings.TrimSpace(s.cfg.WeekStar.RetryStreamKey) + ":pending:" + strconv.FormatInt(recordID, 10) }