package task import ( "context" "encoding/json" "fmt" "tyapi-server/internal/domains/article/repositories" "github.com/hibiken/asynq" "go.uber.org/zap" ) // ArticlePublisher 文章发布接口 type ArticlePublisher interface { PublishArticleByID(ctx context.Context, articleID string) error } // ArticleTaskHandler 文章任务处理器 type ArticleTaskHandler struct { publisher ArticlePublisher scheduledTaskRepo repositories.ScheduledTaskRepository logger *zap.Logger } // NewArticleTaskHandler 创建文章任务处理器 func NewArticleTaskHandler( publisher ArticlePublisher, scheduledTaskRepo repositories.ScheduledTaskRepository, logger *zap.Logger, ) *ArticleTaskHandler { return &ArticleTaskHandler{ publisher: publisher, scheduledTaskRepo: scheduledTaskRepo, logger: logger, } } // HandleArticlePublish 处理文章定时发布任务 func (h *ArticleTaskHandler) HandleArticlePublish(ctx context.Context, t *asynq.Task) error { var payload map[string]interface{} if err := json.Unmarshal(t.Payload(), &payload); err != nil { h.logger.Error("解析任务载荷失败", zap.Error(err)) return fmt.Errorf("解析任务载荷失败: %w", err) } articleID, ok := payload["article_id"].(string) if !ok { h.logger.Error("任务载荷中缺少文章ID") return fmt.Errorf("任务载荷中缺少文章ID") } // 获取任务状态记录 task, err := h.scheduledTaskRepo.GetByTaskID(ctx, t.ResultWriter().TaskID()) if err != nil { h.logger.Error("获取任务状态记录失败", zap.String("task_id", t.ResultWriter().TaskID()), zap.Error(err)) // 继续执行,不阻断任务 } else { // 检查任务是否已取消 if task.IsCancelled() { h.logger.Info("任务已取消,跳过执行", zap.String("task_id", t.ResultWriter().TaskID())) return nil } // 标记任务为正在执行 task.MarkAsRunning() if err := h.scheduledTaskRepo.Update(ctx, task); err != nil { h.logger.Warn("更新任务状态失败", zap.String("task_id", t.ResultWriter().TaskID()), zap.Error(err)) } } // 执行文章发布 if err := h.publisher.PublishArticleByID(ctx, articleID); err != nil { // 更新任务状态为失败 if task.ID != "" { task.MarkAsFailed(err.Error()) if updateErr := h.scheduledTaskRepo.Update(ctx, task); updateErr != nil { h.logger.Warn("更新任务失败状态失败", zap.String("task_id", t.ResultWriter().TaskID()), zap.Error(updateErr)) } } h.logger.Error("定时发布文章失败", zap.String("article_id", articleID), zap.Error(err)) return fmt.Errorf("定时发布文章失败: %w", err) } // 更新任务状态为已完成 if task.ID != "" { task.MarkAsCompleted() if err := h.scheduledTaskRepo.Update(ctx, task); err != nil { h.logger.Warn("更新任务完成状态失败", zap.String("task_id", t.ResultWriter().TaskID()), zap.Error(err)) } } h.logger.Info("定时发布文章成功", zap.String("article_id", articleID)) return nil }