# -*- coding: utf-8 -*- """ 任务结果模型 定义错误码、重试配置、任务结果等数据结构。 """ from enum import Enum from dataclasses import dataclass from typing import Optional, Dict, Any, List class ErrorCode(Enum): """错误码枚举""" E_INPUT_UNAVAILABLE = "E_INPUT_UNAVAILABLE" # 素材不可访问/404 E_FFMPEG_FAILED = "E_FFMPEG_FAILED" # FFmpeg 执行失败 E_UPLOAD_FAILED = "E_UPLOAD_FAILED" # 上传失败 E_SPEC_INVALID = "E_SPEC_INVALID" # renderSpec 非法 E_TIMEOUT = "E_TIMEOUT" # 执行超时 E_UNKNOWN = "E_UNKNOWN" # 未知错误 # 重试配置 RETRY_CONFIG: Dict[ErrorCode, Dict[str, Any]] = { ErrorCode.E_INPUT_UNAVAILABLE: { 'max_retries': 3, 'backoff': [1, 2, 5] # 重试间隔(秒) }, ErrorCode.E_FFMPEG_FAILED: { 'max_retries': 2, 'backoff': [1, 3] }, ErrorCode.E_UPLOAD_FAILED: { 'max_retries': 3, 'backoff': [1, 2, 5] }, ErrorCode.E_SPEC_INVALID: { 'max_retries': 0, # 不重试 'backoff': [] }, ErrorCode.E_TIMEOUT: { 'max_retries': 2, 'backoff': [5, 10] }, ErrorCode.E_UNKNOWN: { 'max_retries': 1, 'backoff': [2] }, } @dataclass class TaskResult: """ 任务结果 封装任务执行的结果,包括成功数据或失败信息。 """ success: bool data: Optional[Dict[str, Any]] = None error_code: Optional[ErrorCode] = None error_message: Optional[str] = None @classmethod def ok(cls, data: Dict[str, Any]) -> 'TaskResult': """创建成功结果""" return cls(success=True, data=data) @classmethod def fail(cls, error_code: ErrorCode, error_message: str) -> 'TaskResult': """创建失败结果""" return cls( success=False, error_code=error_code, error_message=error_message ) def to_report_dict(self) -> Dict[str, Any]: """ 转换为上报格式 用于 API 上报时的数据格式转换。 """ if self.success: return {'result': self.data} else: return { 'errorCode': self.error_code.value if self.error_code else 'E_UNKNOWN', 'errorMessage': self.error_message or 'Unknown error' } def can_retry(self) -> bool: """是否可以重试""" if self.success: return False if not self.error_code: return True config = RETRY_CONFIG.get(self.error_code, {}) return config.get('max_retries', 0) > 0 def get_retry_config(self) -> Dict[str, Any]: """获取重试配置""" if not self.error_code: return {'max_retries': 1, 'backoff': [2]} return RETRY_CONFIG.get(self.error_code, {'max_retries': 1, 'backoff': [2]})