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

392 lines
13 KiB
Python

"""
任务队列管理服务
管理Celery任务的提交、监控和状态查询
"""
import logging
from typing import Dict, Any, Optional, List
from celery.result import AsyncResult
from sqlalchemy.orm import Session
from ..core.celery_app import celery_app
from ..core.database import SessionLocal
from ..models.task import Task, TaskStatus, TaskType
from ..repositories.task_repository import TaskRepository
from ..tasks.processing import process_video_pipeline, process_single_step, retry_processing_step
from ..tasks.video import extract_video_clips, generate_video_collections, optimize_video_quality
from ..tasks.notification import send_processing_notification, send_error_notification, send_completion_notification
from ..tasks.maintenance import cleanup_expired_tasks, health_check, backup_project_data
logger = logging.getLogger(__name__)
class TaskQueueService:
"""任务队列管理服务"""
def __init__(self, db: Session):
self.db = db
self.task_repo = TaskRepository(db)
def submit_video_processing_task(
self,
project_id: str,
input_video_path: str,
input_srt_path: Optional[str] = None,
) -> Dict[str, Any]:
"""
提交视频处理任务
Args:
project_id: 项目ID
input_video_path: 输入视频路径
input_srt_path: 输入SRT路径
Returns:
任务提交结果
"""
logger.info(f"提交视频处理任务: {project_id}")
try:
# 创建并保存任务记录
task = self.task_repo.create(
project_id=project_id,
name="视频流水线处理",
description=f"处理项目 {project_id} 的视频流水线",
task_type=TaskType.VIDEO_PROCESSING,
status=TaskStatus.PENDING,
priority=1
)
# 提交Celery任务
celery_task = process_video_pipeline.delay(
project_id=project_id,
input_video_path=input_video_path,
input_srt_path=input_srt_path,
)
# 更新任务记录
task.celery_task_id = celery_task.id
self.db.commit()
logger.info(f"视频处理任务已提交: {task.id}, Celery任务ID: {celery_task.id}")
return {
'success': True,
'task_id': task.id,
'celery_task_id': celery_task.id,
'status': 'PENDING',
'message': '视频处理任务已提交'
}
except Exception as e:
logger.error(f"提交视频处理任务失败: {project_id}, 错误: {e}")
raise
def submit_single_step_task(
self,
project_id: str,
step_name: str,
config: Optional[Dict[str, Any]] = None,
) -> Dict[str, Any]:
"""
提交单个步骤处理任务
Args:
project_id: 项目ID
step_name: 步骤名称
config: 步骤配置参数
Returns:
任务提交结果
"""
logger.info(f"提交单个步骤任务: {project_id}, {step_name}")
try:
# 创建并保存任务记录
task = self.task_repo.create(
project_id=project_id,
name=f"步骤处理: {step_name}",
description=f"处理项目 {project_id} 的步骤 {step_name}",
task_type=TaskType.VIDEO_PROCESSING,
status=TaskStatus.PENDING,
priority=2
)
# 提交Celery任务
celery_task = process_single_step.delay(project_id, step_name, config or {})
# 更新任务记录
task.celery_task_id = celery_task.id
self.db.commit()
logger.info(f"单个步骤任务已提交: {task.id}, Celery任务ID: {celery_task.id}")
return {
'success': True,
'task_id': task.id,
'celery_task_id': celery_task.id,
'step': step_name,
'status': 'PENDING',
'message': f'步骤 {step_name} 处理任务已提交'
}
except Exception as e:
logger.error(f"提交单个步骤任务失败: {project_id}, {step_name}, 错误: {e}")
raise
def submit_retry_task(
self,
project_id: str,
task_id: str,
step_name: str,
config: Optional[Dict[str, Any]] = None,
) -> Dict[str, Any]:
"""
提交重试任务
Args:
project_id: 项目ID
task_id: 任务ID
step_name: 步骤名称
config: 步骤配置参数
Returns:
任务提交结果
"""
logger.info(f"提交重试任务: {project_id}, {task_id}, {step_name}")
try:
# 创建并保存任务记录
task = self.task_repo.create(
project_id=project_id,
name=f"重试步骤: {step_name}",
description=f"重试项目 {project_id} 的步骤 {step_name}",
task_type=TaskType.VIDEO_PROCESSING,
status=TaskStatus.PENDING,
priority=3
)
# 提交Celery任务
celery_task = retry_processing_step.delay(project_id, step_name, config or {}, task_id)
# 更新任务记录
task.celery_task_id = celery_task.id
self.db.commit()
logger.info(f"重试任务已提交: {task.id}, Celery任务ID: {celery_task.id}")
return {
'success': True,
'task_id': task.id,
'celery_task_id': celery_task.id,
'original_task_id': task_id,
'step': step_name,
'status': 'PENDING',
'message': f'步骤 {step_name} 重试任务已提交'
}
except Exception as e:
logger.error(f"提交重试任务失败: {project_id}, {task_id}, {step_name}, 错误: {e}")
raise
def get_task_status(self, task_id: str) -> Dict[str, Any]:
"""
获取任务状态
Args:
task_id: 任务ID
Returns:
任务状态信息
"""
try:
# 获取数据库任务记录
task = self.task_repo.get_by_id(task_id)
if not task:
return {'error': '任务不存在'}
# 获取Celery任务状态
celery_status = {}
if task.celery_task_id:
celery_result = AsyncResult(task.celery_task_id, app=celery_app)
celery_status = {
'celery_task_id': task.celery_task_id,
'celery_status': celery_result.status,
'celery_result': celery_result.result if celery_result.ready() else None,
'celery_info': celery_result.info if hasattr(celery_result, 'info') else None
}
return {
'task_id': task.id,
'project_id': task.project_id,
'name': task.name,
'status': task.status.value,
'task_type': task.task_type.value,
'progress': task.progress,
'error_message': task.error_message,
'result': task.result_data,
'created_at': task.created_at.isoformat(),
'updated_at': task.updated_at.isoformat(),
'celery_status': celery_status
}
except Exception as e:
logger.error(f"获取任务状态失败: {task_id}, 错误: {e}")
return {'error': f'获取任务状态失败: {e}'}
def get_project_tasks(self, project_id: str) -> List[Dict[str, Any]]:
"""
获取项目的所有任务
Args:
project_id: 项目ID
Returns:
任务列表
"""
try:
tasks = self.task_repo.get_by_project(project_id)
return [
{
'task_id': task.id,
'name': task.name,
'status': task.status.value,
'task_type': task.task_type.value,
'progress': task.progress,
'created_at': task.created_at.isoformat(),
'updated_at': task.updated_at.isoformat()
}
for task in tasks
]
except Exception as e:
logger.error(f"获取项目任务失败: {project_id}, 错误: {e}")
return []
def cancel_task(self, task_id: str) -> Dict[str, Any]:
"""
取消任务
Args:
task_id: 任务ID
Returns:
取消结果
"""
try:
task = self.task_repo.get_by_id(task_id)
if not task:
return {'error': '任务不存在'}
# 取消Celery任务
if task.celery_task_id:
celery_result = AsyncResult(task.celery_task_id, app=celery_app)
celery_result.revoke(terminate=True)
# 更新任务状态
task.status = TaskStatus.CANCELLED
self.db.commit()
logger.info(f"任务已取消: {task_id}")
return {
'success': True,
'task_id': task_id,
'status': 'CANCELLED',
'message': '任务已取消'
}
except Exception as e:
logger.error(f"取消任务失败: {task_id}, 错误: {e}")
return {'error': f'取消任务失败: {e}'}
def submit_video_clips_task(self, project_id: str, clip_data: List[Dict[str, Any]]) -> Dict[str, Any]:
"""
提交视频片段提取任务
Args:
project_id: 项目ID
clip_data: 片段数据
Returns:
任务提交结果
"""
logger.info(f"提交视频片段提取任务: {project_id}")
try:
# 创建并保存任务记录
task = self.task_repo.create(
project_id=project_id,
name="视频片段提取",
description=f"提取项目 {project_id} 的视频片段",
task_type=TaskType.VIDEO_PROCESSING,
status=TaskStatus.PENDING,
priority=2
)
# 提交Celery任务
celery_task = extract_video_clips.delay(project_id, clip_data)
# 更新任务记录
task.celery_task_id = celery_task.id
self.db.commit()
logger.info(f"视频片段提取任务已提交: {task.id}, Celery任务ID: {celery_task.id}")
return {
'success': True,
'task_id': task.id,
'celery_task_id': celery_task.id,
'clip_count': len(clip_data),
'status': 'PENDING',
'message': f'视频片段提取任务已提交,共 {len(clip_data)} 个片段'
}
except Exception as e:
logger.error(f"提交视频片段提取任务失败: {project_id}, 错误: {e}")
raise
def submit_collection_generation_task(self, project_id: str, collection_data: List[Dict[str, Any]]) -> Dict[str, Any]:
"""
提交合集生成任务
Args:
project_id: 项目ID
collection_data: 合集数据
Returns:
任务提交结果
"""
logger.info(f"提交合集生成任务: {project_id}")
try:
# 创建并保存任务记录
task = self.task_repo.create(
project_id=project_id,
name="视频合集生成",
description=f"生成项目 {project_id} 的视频合集",
task_type=TaskType.VIDEO_PROCESSING,
status=TaskStatus.PENDING,
priority=2
)
# 提交Celery任务
celery_task = generate_video_collections.delay(project_id, collection_data)
# 更新任务记录
task.celery_task_id = celery_task.id
self.db.commit()
logger.info(f"合集生成任务已提交: {task.id}, Celery任务ID: {celery_task.id}")
return {
'success': True,
'task_id': task.id,
'celery_task_id': celery_task.id,
'collection_count': len(collection_data),
'status': 'PENDING',
'message': f'视频合集生成任务已提交,共 {len(collection_data)} 个合集'
}
except Exception as e:
logger.error(f"提交合集生成任务失败: {project_id}, 错误: {e}")
raise