Files
wehub-resource-sync 41b710f9c7
CI / Frontend checks (push) Failing after 0s
CI / Backend tests (push) Failing after 1s
I18n Documentation Sync / sync-docs (push) Failing after 0s
chore: import upstream snapshot with attribution
2026-07-13 12:28:40 +08:00

225 lines
6.2 KiB
Python

"""
任务模型
定义后台任务的基本信息和执行状态
"""
import enum
from sqlalchemy import Column, String, Integer, Float, ForeignKey, Enum, JSON, DateTime, Text
from sqlalchemy.orm import relationship
from .base import BaseModel, TimestampMixin
class TaskStatus(str, enum.Enum):
"""任务状态枚举"""
PENDING = "pending" # 等待中
RUNNING = "running" # 运行中
COMPLETED = "completed" # 已完成
FAILED = "failed" # 失败
CANCELLED = "cancelled" # 已取消
class TaskType(str, enum.Enum):
"""任务类型枚举"""
VIDEO_PROCESSING = "video_processing" # 视频处理
CLIP_GENERATION = "clip_generation" # 切片生成
COLLECTION_CREATION = "collection_creation" # 合集创建
EXPORT = "export" # 导出
CLEANUP = "cleanup" # 清理
class Task(BaseModel, TimestampMixin):
"""任务模型"""
__tablename__ = "tasks"
# 基本信息
name = Column(
String(255),
nullable=False,
comment="任务名称"
)
description = Column(
Text,
nullable=True,
comment="任务描述"
)
# 状态信息
status = Column(
Enum(TaskStatus),
default=TaskStatus.PENDING,
nullable=False,
comment="任务状态"
)
task_type = Column(
Enum(TaskType),
nullable=False,
comment="任务类型"
)
# 进度信息
progress = Column(Float, default=0.0, comment="进度百分比")
current_step = Column(
String(100),
nullable=True,
comment="当前步骤"
)
total_steps = Column(
Integer,
default=1,
comment="总步骤数"
)
priority = Column(
Integer,
default=0,
comment="任务优先级"
)
# 执行信息
started_at = Column(
DateTime,
nullable=True,
comment="开始时间"
)
completed_at = Column(
DateTime,
nullable=True,
comment="完成时间"
)
error_message = Column(
Text,
nullable=True,
comment="错误信息"
)
# Celery任务信息
celery_task_id = Column(
String(255),
nullable=True,
comment="Celery任务ID"
)
# 配置信息
task_config = Column(
JSON,
nullable=True,
comment="任务配置"
)
result_data = Column(
JSON,
nullable=True,
comment="结果数据"
)
task_metadata = Column(
JSON,
nullable=True,
comment="任务元数据"
)
# 关联关系
project_id = Column(
String(36),
ForeignKey("projects.id"),
nullable=False,
comment="关联项目ID"
)
project = relationship(
"Project",
back_populates="tasks"
)
def __repr__(self):
return f"<Task(id={self.id}, name='{self.name}', status={self.status})>"
@property
def is_running(self):
"""是否正在运行"""
return self.status == TaskStatus.RUNNING
@property
def is_completed(self):
"""是否已完成"""
return self.status == TaskStatus.COMPLETED
@property
def has_error(self):
"""是否有错误"""
return self.status == TaskStatus.FAILED
@property
def duration(self):
"""任务持续时间(秒)"""
if self.started_at and self.completed_at:
return (self.completed_at - self.started_at).total_seconds()
elif self.started_at:
return (datetime.utcnow() - self.started_at).total_seconds()
return 0
def start(self):
"""开始任务"""
self.status = TaskStatus.RUNNING
self.started_at = datetime.utcnow()
self.progress = 0.0
def complete(self, result_data=None):
"""完成任务"""
self.status = TaskStatus.COMPLETED
self.completed_at = datetime.utcnow()
self.progress = 100.0
if result_data:
self.result_data = result_data
def fail(self, error_message):
"""任务失败"""
self.status = TaskStatus.FAILED
self.completed_at = datetime.utcnow()
self.error_message = error_message
def cancel(self):
"""取消任务"""
self.status = TaskStatus.CANCELLED
self.completed_at = datetime.utcnow()
def update_progress(self, progress, current_step=None):
"""更新进度"""
self.progress = min(100.0, max(0.0, progress))
if current_step:
self.current_step = current_step
def is_completed(self):
"""检查是否完成"""
return self.status in [TaskStatus.COMPLETED, TaskStatus.FAILED, TaskStatus.CANCELLED]
def is_running(self):
"""检查是否运行中"""
return self.status == TaskStatus.RUNNING
def is_pending(self):
"""检查是否待处理"""
return self.status == TaskStatus.PENDING
def get_duration(self):
"""获取任务持续时间"""
if not self.started_at:
return None
end_time = self.completed_at or datetime.utcnow()
return (end_time - self.started_at).total_seconds()
def to_dict(self):
"""转换为字典"""
return {
"id": self.id,
"name": self.name,
"description": self.description,
"task_type": self.task_type,
"status": self.status,
"project_id": self.project_id,
"step": self.current_step,
"total_steps": self.total_steps,
"progress": self.progress,
"result": self.result_data,
"error_message": self.error_message,
"started_at": self.started_at.isoformat() if self.started_at else None,
"completed_at": self.completed_at.isoformat() if self.completed_at else None,
"config": self.task_config,
"created_at": self.created_at.isoformat() if self.created_at else None,
"updated_at": self.updated_at.isoformat() if self.updated_at else None
}