new
This commit is contained in:
285
internal/infrastructure/task/handlers/api_task_handler.go
Normal file
285
internal/infrastructure/task/handlers/api_task_handler.go
Normal file
@@ -0,0 +1,285 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/hibiken/asynq"
|
||||
"github.com/shopspring/decimal"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"tyapi-server/internal/application/api"
|
||||
finance_services "tyapi-server/internal/domains/finance/services"
|
||||
product_services "tyapi-server/internal/domains/product/services"
|
||||
"tyapi-server/internal/infrastructure/task/entities"
|
||||
"tyapi-server/internal/infrastructure/task/repositories"
|
||||
"tyapi-server/internal/infrastructure/task/types"
|
||||
)
|
||||
|
||||
// ApiTaskHandler API任务处理器
|
||||
type ApiTaskHandler struct {
|
||||
logger *zap.Logger
|
||||
apiApplicationService api.ApiApplicationService
|
||||
walletService finance_services.WalletAggregateService
|
||||
subscriptionService *product_services.ProductSubscriptionService
|
||||
asyncTaskRepo repositories.AsyncTaskRepository
|
||||
}
|
||||
|
||||
// NewApiTaskHandler 创建API任务处理器
|
||||
func NewApiTaskHandler(
|
||||
logger *zap.Logger,
|
||||
apiApplicationService api.ApiApplicationService,
|
||||
walletService finance_services.WalletAggregateService,
|
||||
subscriptionService *product_services.ProductSubscriptionService,
|
||||
asyncTaskRepo repositories.AsyncTaskRepository,
|
||||
) *ApiTaskHandler {
|
||||
return &ApiTaskHandler{
|
||||
logger: logger,
|
||||
apiApplicationService: apiApplicationService,
|
||||
walletService: walletService,
|
||||
subscriptionService: subscriptionService,
|
||||
asyncTaskRepo: asyncTaskRepo,
|
||||
}
|
||||
}
|
||||
|
||||
// HandleApiCall 处理API调用任务
|
||||
func (h *ApiTaskHandler) HandleApiCall(ctx context.Context, t *asynq.Task) error {
|
||||
h.logger.Info("开始处理API调用任务")
|
||||
|
||||
var payload types.ApiCallPayload
|
||||
if err := json.Unmarshal(t.Payload(), &payload); err != nil {
|
||||
h.logger.Error("解析API调用任务载荷失败", zap.Error(err))
|
||||
h.updateTaskStatus(ctx, t, "failed", "解析任务载荷失败")
|
||||
return err
|
||||
}
|
||||
|
||||
h.logger.Info("处理API调用任务",
|
||||
zap.String("api_call_id", payload.ApiCallID),
|
||||
zap.String("user_id", payload.UserID),
|
||||
zap.String("product_id", payload.ProductID))
|
||||
|
||||
// 这里实现API调用的具体逻辑
|
||||
// 例如:记录API调用、更新使用统计等
|
||||
|
||||
// 更新任务状态为成功
|
||||
h.updateTaskStatus(ctx, t, "completed", "")
|
||||
h.logger.Info("API调用任务处理完成", zap.String("api_call_id", payload.ApiCallID))
|
||||
return nil
|
||||
}
|
||||
|
||||
// HandleDeduction 处理扣款任务
|
||||
func (h *ApiTaskHandler) HandleDeduction(ctx context.Context, t *asynq.Task) error {
|
||||
h.logger.Info("开始处理扣款任务")
|
||||
|
||||
var payload types.DeductionPayload
|
||||
if err := json.Unmarshal(t.Payload(), &payload); err != nil {
|
||||
h.logger.Error("解析扣款任务载荷失败", zap.Error(err))
|
||||
h.updateTaskStatus(ctx, t, "failed", "解析任务载荷失败")
|
||||
return err
|
||||
}
|
||||
|
||||
h.logger.Info("处理扣款任务",
|
||||
zap.String("user_id", payload.UserID),
|
||||
zap.String("amount", payload.Amount),
|
||||
zap.String("transaction_id", payload.TransactionID))
|
||||
|
||||
// 调用钱包服务进行扣款
|
||||
if h.walletService != nil {
|
||||
amount, err := decimal.NewFromString(payload.Amount)
|
||||
if err != nil {
|
||||
h.logger.Error("金额格式错误", zap.Error(err))
|
||||
h.updateTaskStatus(ctx, t, "failed", "金额格式错误")
|
||||
return err
|
||||
}
|
||||
|
||||
if err := h.walletService.Deduct(ctx, payload.UserID, amount, payload.ApiCallID, payload.TransactionID, payload.ProductID); err != nil {
|
||||
h.logger.Error("扣款处理失败", zap.Error(err))
|
||||
h.updateTaskStatus(ctx, t, "failed", "扣款处理失败: "+err.Error())
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
h.logger.Warn("钱包服务未初始化,跳过扣款", zap.String("user_id", payload.UserID))
|
||||
h.updateTaskStatus(ctx, t, "failed", "钱包服务未初始化")
|
||||
return nil
|
||||
}
|
||||
|
||||
// 更新任务状态为成功
|
||||
h.updateTaskStatus(ctx, t, "completed", "")
|
||||
h.logger.Info("扣款任务处理完成", zap.String("transaction_id", payload.TransactionID))
|
||||
return nil
|
||||
}
|
||||
|
||||
// HandleCompensation 处理补偿任务
|
||||
func (h *ApiTaskHandler) HandleCompensation(ctx context.Context, t *asynq.Task) error {
|
||||
h.logger.Info("开始处理补偿任务")
|
||||
|
||||
var payload types.CompensationPayload
|
||||
if err := json.Unmarshal(t.Payload(), &payload); err != nil {
|
||||
h.logger.Error("解析补偿任务载荷失败", zap.Error(err))
|
||||
return err
|
||||
}
|
||||
|
||||
h.logger.Info("处理补偿任务",
|
||||
zap.String("transaction_id", payload.TransactionID),
|
||||
zap.String("type", payload.Type))
|
||||
|
||||
// 这里实现补偿的具体逻辑
|
||||
// 例如:调用钱包服务进行退款等
|
||||
|
||||
h.logger.Info("补偿任务处理完成", zap.String("transaction_id", payload.TransactionID))
|
||||
return nil
|
||||
}
|
||||
|
||||
// HandleUsageStats 处理使用统计任务
|
||||
func (h *ApiTaskHandler) HandleUsageStats(ctx context.Context, t *asynq.Task) error {
|
||||
h.logger.Info("开始处理使用统计任务")
|
||||
|
||||
var payload types.UsageStatsPayload
|
||||
if err := json.Unmarshal(t.Payload(), &payload); err != nil {
|
||||
h.logger.Error("解析使用统计任务载荷失败", zap.Error(err))
|
||||
h.updateTaskStatus(ctx, t, "failed", "解析任务载荷失败")
|
||||
return err
|
||||
}
|
||||
|
||||
h.logger.Info("处理使用统计任务",
|
||||
zap.String("subscription_id", payload.SubscriptionID),
|
||||
zap.String("user_id", payload.UserID),
|
||||
zap.Int("increment", payload.Increment))
|
||||
|
||||
// 调用订阅服务更新使用统计
|
||||
if h.subscriptionService != nil {
|
||||
if err := h.subscriptionService.IncrementSubscriptionAPIUsage(ctx, payload.SubscriptionID, int64(payload.Increment)); err != nil {
|
||||
h.logger.Error("更新使用统计失败", zap.Error(err))
|
||||
h.updateTaskStatus(ctx, t, "failed", "更新使用统计失败: "+err.Error())
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
h.logger.Warn("订阅服务未初始化,跳过使用统计更新", zap.String("subscription_id", payload.SubscriptionID))
|
||||
h.updateTaskStatus(ctx, t, "failed", "订阅服务未初始化")
|
||||
return nil
|
||||
}
|
||||
|
||||
// 更新任务状态为成功
|
||||
h.updateTaskStatus(ctx, t, "completed", "")
|
||||
h.logger.Info("使用统计任务处理完成", zap.String("subscription_id", payload.SubscriptionID))
|
||||
return nil
|
||||
}
|
||||
|
||||
// HandleApiLog 处理API日志任务
|
||||
func (h *ApiTaskHandler) HandleApiLog(ctx context.Context, t *asynq.Task) error {
|
||||
h.logger.Info("开始处理API日志任务")
|
||||
|
||||
var payload types.ApiLogPayload
|
||||
if err := json.Unmarshal(t.Payload(), &payload); err != nil {
|
||||
h.logger.Error("解析API日志任务载荷失败", zap.Error(err))
|
||||
h.updateTaskStatus(ctx, t, "failed", "解析任务载荷失败")
|
||||
return err
|
||||
}
|
||||
|
||||
h.logger.Info("处理API日志任务",
|
||||
zap.String("transaction_id", payload.TransactionID),
|
||||
zap.String("user_id", payload.UserID),
|
||||
zap.String("api_name", payload.ApiName),
|
||||
zap.String("product_id", payload.ProductID))
|
||||
|
||||
// 记录结构化日志
|
||||
h.logger.Info("API调用日志",
|
||||
zap.String("transaction_id", payload.TransactionID),
|
||||
zap.String("user_id", payload.UserID),
|
||||
zap.String("api_name", payload.ApiName),
|
||||
zap.String("product_id", payload.ProductID),
|
||||
zap.Time("timestamp", time.Now()))
|
||||
|
||||
// 这里可以添加其他日志记录逻辑
|
||||
// 例如:写入专门的日志文件、发送到日志系统、写入数据库等
|
||||
|
||||
// 更新任务状态为成功
|
||||
h.updateTaskStatus(ctx, t, "completed", "")
|
||||
h.logger.Info("API日志任务处理完成", zap.String("transaction_id", payload.TransactionID))
|
||||
return nil
|
||||
}
|
||||
|
||||
// updateTaskStatus 更新任务状态
|
||||
func (h *ApiTaskHandler) updateTaskStatus(ctx context.Context, t *asynq.Task, status string, errorMsg string) {
|
||||
// 从任务载荷中提取任务ID
|
||||
var payload map[string]interface{}
|
||||
if err := json.Unmarshal(t.Payload(), &payload); err != nil {
|
||||
h.logger.Error("解析任务载荷失败,无法更新状态", zap.Error(err))
|
||||
return
|
||||
}
|
||||
|
||||
// 尝试从payload中获取任务ID
|
||||
taskID, ok := payload["task_id"].(string)
|
||||
if !ok {
|
||||
h.logger.Error("无法从任务载荷中获取任务ID")
|
||||
return
|
||||
}
|
||||
|
||||
// 根据状态决定更新方式
|
||||
if status == "failed" {
|
||||
// 失败时:需要检查是否达到最大重试次数
|
||||
h.handleTaskFailure(ctx, taskID, errorMsg)
|
||||
} else if status == "completed" {
|
||||
// 成功时:清除错误信息并更新状态
|
||||
if err := h.asyncTaskRepo.UpdateStatusWithSuccess(ctx, taskID, entities.TaskStatus(status)); err != nil {
|
||||
h.logger.Error("更新任务状态失败",
|
||||
zap.String("task_id", taskID),
|
||||
zap.String("status", status),
|
||||
zap.Error(err))
|
||||
}
|
||||
} else {
|
||||
// 其他状态:只更新状态
|
||||
if err := h.asyncTaskRepo.UpdateStatus(ctx, taskID, entities.TaskStatus(status)); err != nil {
|
||||
h.logger.Error("更新任务状态失败",
|
||||
zap.String("task_id", taskID),
|
||||
zap.String("status", status),
|
||||
zap.Error(err))
|
||||
}
|
||||
}
|
||||
|
||||
h.logger.Info("任务状态已更新",
|
||||
zap.String("task_id", taskID),
|
||||
zap.String("status", status),
|
||||
zap.String("error_msg", errorMsg))
|
||||
}
|
||||
|
||||
// handleTaskFailure 处理任务失败
|
||||
func (h *ApiTaskHandler) handleTaskFailure(ctx context.Context, taskID string, errorMsg string) {
|
||||
// 获取当前任务信息
|
||||
task, err := h.asyncTaskRepo.GetByID(ctx, taskID)
|
||||
if err != nil {
|
||||
h.logger.Error("获取任务信息失败", zap.String("task_id", taskID), zap.Error(err))
|
||||
return
|
||||
}
|
||||
|
||||
// 增加重试次数
|
||||
newRetryCount := task.RetryCount + 1
|
||||
|
||||
// 检查是否达到最大重试次数
|
||||
if newRetryCount >= task.MaxRetries {
|
||||
// 达到最大重试次数,标记为最终失败
|
||||
if err := h.asyncTaskRepo.UpdateStatusWithRetryAndError(ctx, taskID, entities.TaskStatusFailed, errorMsg); err != nil {
|
||||
h.logger.Error("更新任务状态失败",
|
||||
zap.String("task_id", taskID),
|
||||
zap.String("status", "failed"),
|
||||
zap.Error(err))
|
||||
}
|
||||
h.logger.Info("任务最终失败,已达到最大重试次数",
|
||||
zap.String("task_id", taskID),
|
||||
zap.Int("retry_count", newRetryCount),
|
||||
zap.Int("max_retries", task.MaxRetries))
|
||||
} else {
|
||||
// 未达到最大重试次数,保持pending状态,记录错误信息
|
||||
if err := h.asyncTaskRepo.UpdateRetryCountAndError(ctx, taskID, newRetryCount, errorMsg); err != nil {
|
||||
h.logger.Error("更新任务重试次数失败",
|
||||
zap.String("task_id", taskID),
|
||||
zap.Int("retry_count", newRetryCount),
|
||||
zap.Error(err))
|
||||
}
|
||||
h.logger.Info("任务失败,准备重试",
|
||||
zap.String("task_id", taskID),
|
||||
zap.Int("retry_count", newRetryCount),
|
||||
zap.Int("max_retries", task.MaxRetries))
|
||||
}
|
||||
}
|
||||
304
internal/infrastructure/task/handlers/article_task_handler.go
Normal file
304
internal/infrastructure/task/handlers/article_task_handler.go
Normal file
@@ -0,0 +1,304 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/hibiken/asynq"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"tyapi-server/internal/application/article"
|
||||
"tyapi-server/internal/infrastructure/task/entities"
|
||||
"tyapi-server/internal/infrastructure/task/repositories"
|
||||
"tyapi-server/internal/infrastructure/task/types"
|
||||
)
|
||||
|
||||
// ArticleTaskHandler 文章任务处理器
|
||||
type ArticleTaskHandler struct {
|
||||
logger *zap.Logger
|
||||
articleApplicationService article.ArticleApplicationService
|
||||
asyncTaskRepo repositories.AsyncTaskRepository
|
||||
}
|
||||
|
||||
// NewArticleTaskHandler 创建文章任务处理器
|
||||
func NewArticleTaskHandler(logger *zap.Logger, articleApplicationService article.ArticleApplicationService, asyncTaskRepo repositories.AsyncTaskRepository) *ArticleTaskHandler {
|
||||
return &ArticleTaskHandler{
|
||||
logger: logger,
|
||||
articleApplicationService: articleApplicationService,
|
||||
asyncTaskRepo: asyncTaskRepo,
|
||||
}
|
||||
}
|
||||
|
||||
// HandleArticlePublish 处理文章发布任务
|
||||
func (h *ArticleTaskHandler) HandleArticlePublish(ctx context.Context, t *asynq.Task) error {
|
||||
h.logger.Info("开始处理文章发布任务")
|
||||
|
||||
var payload ArticlePublishPayload
|
||||
if err := json.Unmarshal(t.Payload(), &payload); err != nil {
|
||||
h.logger.Error("解析文章发布任务载荷失败", zap.Error(err))
|
||||
h.updateTaskStatus(ctx, t, "failed", "解析任务载荷失败")
|
||||
return err
|
||||
}
|
||||
|
||||
h.logger.Info("处理文章发布任务",
|
||||
zap.String("article_id", payload.ArticleID),
|
||||
zap.Time("publish_at", payload.PublishAt))
|
||||
|
||||
// 检查任务是否已被取消
|
||||
if err := h.checkTaskStatus(ctx, t); err != nil {
|
||||
h.logger.Info("任务已被取消,跳过执行", zap.String("article_id", payload.ArticleID))
|
||||
return nil // 静默返回,不报错
|
||||
}
|
||||
|
||||
// 调用文章应用服务发布文章
|
||||
if h.articleApplicationService != nil {
|
||||
err := h.articleApplicationService.PublishArticleByID(ctx, payload.ArticleID)
|
||||
if err != nil {
|
||||
h.logger.Error("文章发布失败", zap.String("article_id", payload.ArticleID), zap.Error(err))
|
||||
h.updateTaskStatus(ctx, t, "failed", "文章发布失败: "+err.Error())
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
h.logger.Warn("文章应用服务未初始化,跳过发布", zap.String("article_id", payload.ArticleID))
|
||||
h.updateTaskStatus(ctx, t, "failed", "文章应用服务未初始化")
|
||||
return nil
|
||||
}
|
||||
|
||||
// 更新任务状态为成功
|
||||
h.updateTaskStatus(ctx, t, "completed", "")
|
||||
h.logger.Info("文章发布任务处理完成", zap.String("article_id", payload.ArticleID))
|
||||
return nil
|
||||
}
|
||||
|
||||
// HandleArticleCancel 处理文章取消任务
|
||||
func (h *ArticleTaskHandler) HandleArticleCancel(ctx context.Context, t *asynq.Task) error {
|
||||
h.logger.Info("开始处理文章取消任务")
|
||||
|
||||
var payload ArticleCancelPayload
|
||||
if err := json.Unmarshal(t.Payload(), &payload); err != nil {
|
||||
h.logger.Error("解析文章取消任务载荷失败", zap.Error(err))
|
||||
return err
|
||||
}
|
||||
|
||||
h.logger.Info("处理文章取消任务", zap.String("article_id", payload.ArticleID))
|
||||
|
||||
// 这里实现文章取消的具体逻辑
|
||||
// 例如:更新文章状态、取消定时发布等
|
||||
|
||||
h.logger.Info("文章取消任务处理完成", zap.String("article_id", payload.ArticleID))
|
||||
return nil
|
||||
}
|
||||
|
||||
// HandleArticleModify 处理文章修改任务
|
||||
func (h *ArticleTaskHandler) HandleArticleModify(ctx context.Context, t *asynq.Task) error {
|
||||
h.logger.Info("开始处理文章修改任务")
|
||||
|
||||
var payload ArticleModifyPayload
|
||||
if err := json.Unmarshal(t.Payload(), &payload); err != nil {
|
||||
h.logger.Error("解析文章修改任务载荷失败", zap.Error(err))
|
||||
return err
|
||||
}
|
||||
|
||||
h.logger.Info("处理文章修改任务",
|
||||
zap.String("article_id", payload.ArticleID),
|
||||
zap.Time("new_publish_at", payload.NewPublishAt))
|
||||
|
||||
// 这里实现文章修改的具体逻辑
|
||||
// 例如:更新文章发布时间、重新调度任务等
|
||||
|
||||
h.logger.Info("文章修改任务处理完成", zap.String("article_id", payload.ArticleID))
|
||||
return nil
|
||||
}
|
||||
|
||||
// ArticlePublishPayload 文章发布任务载荷
|
||||
type ArticlePublishPayload struct {
|
||||
ArticleID string `json:"article_id"`
|
||||
PublishAt time.Time `json:"publish_at"`
|
||||
UserID string `json:"user_id"`
|
||||
}
|
||||
|
||||
// GetType 获取任务类型
|
||||
func (p *ArticlePublishPayload) GetType() types.TaskType {
|
||||
return types.TaskTypeArticlePublish
|
||||
}
|
||||
|
||||
// ToJSON 序列化为JSON
|
||||
func (p *ArticlePublishPayload) ToJSON() ([]byte, error) {
|
||||
return json.Marshal(p)
|
||||
}
|
||||
|
||||
// FromJSON 从JSON反序列化
|
||||
func (p *ArticlePublishPayload) FromJSON(data []byte) error {
|
||||
return json.Unmarshal(data, p)
|
||||
}
|
||||
|
||||
// ArticleCancelPayload 文章取消任务载荷
|
||||
type ArticleCancelPayload struct {
|
||||
ArticleID string `json:"article_id"`
|
||||
UserID string `json:"user_id"`
|
||||
}
|
||||
|
||||
// GetType 获取任务类型
|
||||
func (p *ArticleCancelPayload) GetType() types.TaskType {
|
||||
return types.TaskTypeArticleCancel
|
||||
}
|
||||
|
||||
// ToJSON 序列化为JSON
|
||||
func (p *ArticleCancelPayload) ToJSON() ([]byte, error) {
|
||||
return json.Marshal(p)
|
||||
}
|
||||
|
||||
// FromJSON 从JSON反序列化
|
||||
func (p *ArticleCancelPayload) FromJSON(data []byte) error {
|
||||
return json.Unmarshal(data, p)
|
||||
}
|
||||
|
||||
// ArticleModifyPayload 文章修改任务载荷
|
||||
type ArticleModifyPayload struct {
|
||||
ArticleID string `json:"article_id"`
|
||||
NewPublishAt time.Time `json:"new_publish_at"`
|
||||
UserID string `json:"user_id"`
|
||||
}
|
||||
|
||||
// GetType 获取任务类型
|
||||
func (p *ArticleModifyPayload) GetType() types.TaskType {
|
||||
return types.TaskTypeArticleModify
|
||||
}
|
||||
|
||||
// ToJSON 序列化为JSON
|
||||
func (p *ArticleModifyPayload) ToJSON() ([]byte, error) {
|
||||
return json.Marshal(p)
|
||||
}
|
||||
|
||||
// FromJSON 从JSON反序列化
|
||||
func (p *ArticleModifyPayload) FromJSON(data []byte) error {
|
||||
return json.Unmarshal(data, p)
|
||||
}
|
||||
|
||||
// updateTaskStatus 更新任务状态
|
||||
func (h *ArticleTaskHandler) updateTaskStatus(ctx context.Context, t *asynq.Task, status string, errorMsg string) {
|
||||
// 从任务载荷中提取任务ID
|
||||
var payload map[string]interface{}
|
||||
if err := json.Unmarshal(t.Payload(), &payload); err != nil {
|
||||
h.logger.Error("解析任务载荷失败,无法更新状态", zap.Error(err))
|
||||
return
|
||||
}
|
||||
|
||||
// 尝试从payload中获取任务ID
|
||||
taskID, ok := payload["task_id"].(string)
|
||||
if !ok {
|
||||
// 如果没有task_id,尝试从article_id生成
|
||||
if articleID, ok := payload["article_id"].(string); ok {
|
||||
taskID = fmt.Sprintf("article-publish-%s", articleID)
|
||||
} else {
|
||||
h.logger.Error("无法从任务载荷中获取任务ID")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 根据状态决定更新方式
|
||||
if status == "failed" {
|
||||
// 失败时:需要检查是否达到最大重试次数
|
||||
h.handleTaskFailure(ctx, taskID, errorMsg)
|
||||
} else if status == "completed" {
|
||||
// 成功时:清除错误信息并更新状态
|
||||
if err := h.asyncTaskRepo.UpdateStatusWithSuccess(ctx, taskID, entities.TaskStatus(status)); err != nil {
|
||||
h.logger.Error("更新任务状态失败",
|
||||
zap.String("task_id", taskID),
|
||||
zap.String("status", status),
|
||||
zap.Error(err))
|
||||
}
|
||||
} else {
|
||||
// 其他状态:只更新状态
|
||||
if err := h.asyncTaskRepo.UpdateStatus(ctx, taskID, entities.TaskStatus(status)); err != nil {
|
||||
h.logger.Error("更新任务状态失败",
|
||||
zap.String("task_id", taskID),
|
||||
zap.String("status", status),
|
||||
zap.Error(err))
|
||||
}
|
||||
}
|
||||
|
||||
h.logger.Info("任务状态已更新",
|
||||
zap.String("task_id", taskID),
|
||||
zap.String("status", status),
|
||||
zap.String("error_msg", errorMsg))
|
||||
}
|
||||
|
||||
// handleTaskFailure 处理任务失败
|
||||
func (h *ArticleTaskHandler) handleTaskFailure(ctx context.Context, taskID string, errorMsg string) {
|
||||
// 获取当前任务信息
|
||||
task, err := h.asyncTaskRepo.GetByID(ctx, taskID)
|
||||
if err != nil {
|
||||
h.logger.Error("获取任务信息失败", zap.String("task_id", taskID), zap.Error(err))
|
||||
return
|
||||
}
|
||||
|
||||
// 增加重试次数
|
||||
newRetryCount := task.RetryCount + 1
|
||||
|
||||
// 检查是否达到最大重试次数
|
||||
if newRetryCount >= task.MaxRetries {
|
||||
// 达到最大重试次数,标记为最终失败
|
||||
if err := h.asyncTaskRepo.UpdateStatusWithRetryAndError(ctx, taskID, entities.TaskStatusFailed, errorMsg); err != nil {
|
||||
h.logger.Error("更新任务状态失败",
|
||||
zap.String("task_id", taskID),
|
||||
zap.String("status", "failed"),
|
||||
zap.Error(err))
|
||||
}
|
||||
h.logger.Info("任务最终失败,已达到最大重试次数",
|
||||
zap.String("task_id", taskID),
|
||||
zap.Int("retry_count", newRetryCount),
|
||||
zap.Int("max_retries", task.MaxRetries))
|
||||
} else {
|
||||
// 未达到最大重试次数,保持pending状态,记录错误信息
|
||||
if err := h.asyncTaskRepo.UpdateRetryCountAndError(ctx, taskID, newRetryCount, errorMsg); err != nil {
|
||||
h.logger.Error("更新任务重试次数失败",
|
||||
zap.String("task_id", taskID),
|
||||
zap.Int("retry_count", newRetryCount),
|
||||
zap.Error(err))
|
||||
}
|
||||
h.logger.Info("任务失败,准备重试",
|
||||
zap.String("task_id", taskID),
|
||||
zap.Int("retry_count", newRetryCount),
|
||||
zap.Int("max_retries", task.MaxRetries))
|
||||
}
|
||||
}
|
||||
|
||||
// checkTaskStatus 检查任务状态
|
||||
func (h *ArticleTaskHandler) checkTaskStatus(ctx context.Context, t *asynq.Task) error {
|
||||
// 从任务载荷中提取任务ID
|
||||
var payload map[string]interface{}
|
||||
if err := json.Unmarshal(t.Payload(), &payload); err != nil {
|
||||
h.logger.Error("解析任务载荷失败,无法检查状态", zap.Error(err))
|
||||
return err
|
||||
}
|
||||
|
||||
// 尝试从payload中获取任务ID
|
||||
taskID, ok := payload["task_id"].(string)
|
||||
if !ok {
|
||||
// 如果没有task_id,尝试从article_id生成
|
||||
if articleID, ok := payload["article_id"].(string); ok {
|
||||
taskID = fmt.Sprintf("article-publish-%s", articleID)
|
||||
} else {
|
||||
h.logger.Error("无法从任务载荷中获取任务ID")
|
||||
return fmt.Errorf("无法获取任务ID")
|
||||
}
|
||||
}
|
||||
|
||||
// 查询任务状态
|
||||
task, err := h.asyncTaskRepo.GetByID(ctx, taskID)
|
||||
if err != nil {
|
||||
h.logger.Error("查询任务状态失败", zap.String("task_id", taskID), zap.Error(err))
|
||||
return err
|
||||
}
|
||||
|
||||
// 检查任务是否已被取消
|
||||
if task.Status == entities.TaskStatusCancelled {
|
||||
h.logger.Info("任务已被取消", zap.String("task_id", taskID))
|
||||
return fmt.Errorf("任务已被取消")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user