package asynq import ( "context" "fmt" "time" "github.com/hibiken/asynq" "go.uber.org/zap" "tyapi-server/internal/infrastructure/task/entities" "tyapi-server/internal/infrastructure/task/interfaces" "tyapi-server/internal/infrastructure/task/types" ) // AsynqApiTaskQueue Asynq API任务队列实现 type AsynqApiTaskQueue struct { client *asynq.Client logger *zap.Logger } // NewAsynqApiTaskQueue 创建Asynq API任务队列 func NewAsynqApiTaskQueue(redisAddr string, logger *zap.Logger) interfaces.ApiTaskQueue { client := asynq.NewClient(asynq.RedisClientOpt{Addr: redisAddr}) return &AsynqApiTaskQueue{ client: client, logger: logger, } } // Enqueue 入队任务 func (q *AsynqApiTaskQueue) Enqueue(ctx context.Context, taskType types.TaskType, payload types.TaskPayload) error { payloadData, err := payload.ToJSON() if err != nil { q.logger.Error("序列化任务载荷失败", zap.Error(err)) return err } task := asynq.NewTask(string(taskType), payloadData) _, err = q.client.EnqueueContext(ctx, task) if err != nil { q.logger.Error("入队任务失败", zap.String("task_type", string(taskType)), zap.Error(err)) return err } q.logger.Info("任务入队成功", zap.String("task_type", string(taskType))) return nil } // EnqueueDelayed 延时入队任务 func (q *AsynqApiTaskQueue) EnqueueDelayed(ctx context.Context, taskType types.TaskType, payload types.TaskPayload, delay time.Duration) error { payloadData, err := payload.ToJSON() if err != nil { q.logger.Error("序列化任务载荷失败", zap.Error(err)) return err } task := asynq.NewTask(string(taskType), payloadData) _, err = q.client.EnqueueContext(ctx, task, asynq.ProcessIn(delay)) if err != nil { q.logger.Error("延时入队任务失败", zap.String("task_type", string(taskType)), zap.Error(err)) return err } q.logger.Info("延时任务入队成功", zap.String("task_type", string(taskType)), zap.Duration("delay", delay)) return nil } // EnqueueAt 指定时间入队任务 func (q *AsynqApiTaskQueue) EnqueueAt(ctx context.Context, taskType types.TaskType, payload types.TaskPayload, scheduledAt time.Time) error { payloadData, err := payload.ToJSON() if err != nil { q.logger.Error("序列化任务载荷失败", zap.Error(err)) return err } task := asynq.NewTask(string(taskType), payloadData) _, err = q.client.EnqueueContext(ctx, task, asynq.ProcessAt(scheduledAt)) if err != nil { q.logger.Error("定时入队任务失败", zap.String("task_type", string(taskType)), zap.Error(err)) return err } q.logger.Info("定时任务入队成功", zap.String("task_type", string(taskType)), zap.Time("scheduled_at", scheduledAt)) return nil } // Cancel 取消任务 func (q *AsynqApiTaskQueue) Cancel(ctx context.Context, taskID string) error { // Asynq本身不支持直接取消任务,这里返回错误提示 return fmt.Errorf("Asynq不支持直接取消任务,请使用数据库状态管理") } // ModifySchedule 修改任务调度时间 func (q *AsynqApiTaskQueue) ModifySchedule(ctx context.Context, taskID string, newScheduledAt time.Time) error { // Asynq本身不支持修改调度时间,这里返回错误提示 return fmt.Errorf("Asynq不支持修改任务调度时间,请使用数据库状态管理") } // GetTaskStatus 获取任务状态 func (q *AsynqApiTaskQueue) GetTaskStatus(ctx context.Context, taskID string) (*entities.AsyncTask, error) { // Asynq本身不提供任务状态查询,这里返回错误提示 return nil, fmt.Errorf("Asynq不提供任务状态查询,请使用数据库状态管理") } // ListTasks 列出任务 func (q *AsynqApiTaskQueue) ListTasks(ctx context.Context, taskType types.TaskType, status entities.TaskStatus, limit int) ([]*entities.AsyncTask, error) { // Asynq本身不提供任务列表查询,这里返回错误提示 return nil, fmt.Errorf("Asynq不提供任务列表查询,请使用数据库状态管理") } // EnqueueTask 入队任务 func (q *AsynqApiTaskQueue) EnqueueTask(ctx context.Context, task *entities.AsyncTask) error { // 创建Asynq任务 asynqTask := asynq.NewTask(task.Type, []byte(task.Payload)) // 入队任务 _, err := q.client.EnqueueContext(ctx, asynqTask) if err != nil { q.logger.Error("入队任务失败", zap.String("task_id", task.ID), zap.String("task_type", task.Type), zap.Error(err)) return err } q.logger.Info("入队任务成功", zap.String("task_id", task.ID), zap.String("task_type", task.Type)) return nil }