- 修复WebSocketNotificationService.send_processing_progress方法参数不匹配问题 - 修复前端RealTimeStatus组件WebSocket消息处理逻辑 - 修复Celery Worker队列配置,确保任务正确路由到processing队列 - 修复Celery应用导入冲突,统一使用正确的celery_app配置 - 添加实时项目状态更新功能,前端无需手动刷新即可看到处理进度 - 完善系统启动脚本,修复PYTHONPATH未绑定变量错误 - 优化流水线处理逻辑,确保所有6个步骤正常执行 - 添加完整的项目文档和启动指南 测试结果: - WebSocket进度更新正常工作(16%, 33%, 100%) - 流水线处理完全正常(6个步骤全部成功) - 前端状态自动更新正常 - 项目状态正确同步到数据库
327 lines
9.3 KiB
Python
327 lines
9.3 KiB
Python
"""
|
|
任务Repository
|
|
提供任务相关的数据访问操作
|
|
"""
|
|
|
|
from typing import List, Optional
|
|
from sqlalchemy.orm import Session
|
|
from sqlalchemy import desc, asc, func
|
|
from .base import BaseRepository
|
|
from ..models.task import Task, TaskStatus, TaskType
|
|
|
|
class TaskRepository(BaseRepository[Task]):
|
|
"""任务Repository类"""
|
|
|
|
def __init__(self, db: Session):
|
|
super().__init__(Task, db)
|
|
|
|
def find_all(self, skip: int = 0, limit: int = 100, **filters) -> List[Task]:
|
|
"""
|
|
获取所有任务,支持过滤和分页
|
|
|
|
Args:
|
|
skip: 跳过的记录数
|
|
limit: 返回的记录数限制
|
|
**filters: 过滤条件
|
|
|
|
Returns:
|
|
任务列表
|
|
"""
|
|
query = self.db.query(self.model)
|
|
|
|
# 应用过滤条件
|
|
for key, value in filters.items():
|
|
if hasattr(self.model, key) and value is not None:
|
|
query = query.filter(getattr(self.model, key) == value)
|
|
|
|
return query.offset(skip).limit(limit).all()
|
|
|
|
def get_by_project(self, project_id: str) -> List[Task]:
|
|
"""
|
|
获取项目的所有任务
|
|
|
|
Args:
|
|
project_id: 项目ID
|
|
|
|
Returns:
|
|
任务列表
|
|
"""
|
|
return self.find_by(project_id=project_id)
|
|
|
|
def get_by_status(self, status: TaskStatus) -> List[Task]:
|
|
"""
|
|
根据状态获取任务列表
|
|
|
|
Args:
|
|
status: 任务状态
|
|
|
|
Returns:
|
|
任务列表
|
|
"""
|
|
return self.find_by(status=status)
|
|
|
|
def get_by_type(self, task_type: TaskType) -> List[Task]:
|
|
"""
|
|
根据任务类型获取任务列表
|
|
|
|
Args:
|
|
task_type: 任务类型
|
|
|
|
Returns:
|
|
任务列表
|
|
"""
|
|
return self.find_by(task_type=task_type)
|
|
|
|
def get_by_project_and_status(self, project_id: str, status: TaskStatus) -> List[Task]:
|
|
"""
|
|
根据项目和状态获取任务列表
|
|
|
|
Args:
|
|
project_id: 项目ID
|
|
status: 任务状态
|
|
|
|
Returns:
|
|
任务列表
|
|
"""
|
|
return self.find_by(project_id=project_id, status=status)
|
|
|
|
def get_by_project_and_type(self, project_id: str, task_type: TaskType) -> List[Task]:
|
|
"""
|
|
根据项目和任务类型获取任务列表
|
|
|
|
Args:
|
|
project_id: 项目ID
|
|
task_type: 任务类型
|
|
|
|
Returns:
|
|
任务列表
|
|
"""
|
|
return self.find_by(project_id=project_id, task_type=task_type)
|
|
|
|
def get_pending_tasks(self) -> List[Task]:
|
|
"""
|
|
获取待处理的任务
|
|
|
|
Returns:
|
|
待处理任务列表
|
|
"""
|
|
return self.find_by(status=TaskStatus.PENDING)
|
|
|
|
def get_running_tasks(self) -> List[Task]:
|
|
"""
|
|
获取正在运行的任务
|
|
|
|
Returns:
|
|
正在运行的任务列表
|
|
"""
|
|
return self.find_by(status=TaskStatus.RUNNING)
|
|
|
|
def get_completed_tasks(self) -> List[Task]:
|
|
"""
|
|
获取已完成的任务
|
|
|
|
Returns:
|
|
已完成的任务列表
|
|
"""
|
|
return self.find_by(status=TaskStatus.COMPLETED)
|
|
|
|
def get_failed_tasks(self) -> List[Task]:
|
|
"""
|
|
获取失败的任务
|
|
|
|
Returns:
|
|
失败的任务列表
|
|
"""
|
|
return self.find_by(status=TaskStatus.FAILED)
|
|
|
|
def get_tasks_by_step(self, project_id: str, step: int) -> List[Task]:
|
|
"""
|
|
根据处理步骤获取任务
|
|
|
|
Args:
|
|
project_id: 项目ID
|
|
step: 处理步骤
|
|
|
|
Returns:
|
|
任务列表
|
|
"""
|
|
return self.find_by(project_id=project_id, step=step)
|
|
|
|
def get_next_pending_task(self) -> Optional[Task]:
|
|
"""
|
|
获取下一个待处理任务
|
|
|
|
Returns:
|
|
下一个待处理任务或None
|
|
"""
|
|
return self.db.query(self.model).filter(
|
|
self.model.status == TaskStatus.PENDING
|
|
).order_by(asc(self.model.created_at)).first()
|
|
|
|
def get_tasks_by_priority(self, priority: int) -> List[Task]:
|
|
"""
|
|
根据优先级获取任务
|
|
|
|
Args:
|
|
priority: 优先级
|
|
|
|
Returns:
|
|
任务列表
|
|
"""
|
|
return self.find_by(priority=priority)
|
|
|
|
def update_task_status(self, task_id: str, status: TaskStatus) -> Optional[Task]:
|
|
"""
|
|
更新任务状态
|
|
|
|
Args:
|
|
task_id: 任务ID
|
|
status: 新状态
|
|
|
|
Returns:
|
|
更新后的任务实例或None
|
|
"""
|
|
return self.update(task_id, status=status)
|
|
|
|
def update_task_progress(self, task_id: str, progress: float) -> Optional[Task]:
|
|
"""
|
|
更新任务进度
|
|
|
|
Args:
|
|
task_id: 任务ID
|
|
progress: 进度百分比
|
|
|
|
Returns:
|
|
更新后的任务实例或None
|
|
"""
|
|
return self.update(task_id, progress=progress)
|
|
|
|
def update_task_result(self, task_id: str, result: dict) -> Optional[Task]:
|
|
"""
|
|
更新任务结果
|
|
|
|
Args:
|
|
task_id: 任务ID
|
|
result: 任务结果
|
|
|
|
Returns:
|
|
更新后的任务实例或None
|
|
"""
|
|
return self.update(task_id, result=result)
|
|
|
|
def update_task_error(self, task_id: str, error_message: str) -> Optional[Task]:
|
|
"""
|
|
更新任务错误信息
|
|
|
|
Args:
|
|
task_id: 任务ID
|
|
error_message: 错误信息
|
|
|
|
Returns:
|
|
更新后的任务实例或None
|
|
"""
|
|
return self.update(task_id, error_message=error_message, status=TaskStatus.FAILED)
|
|
|
|
def get_tasks_statistics(self, project_id: str = None) -> dict:
|
|
"""
|
|
获取任务统计信息
|
|
|
|
Args:
|
|
project_id: 项目ID,如果为None则统计所有项目
|
|
|
|
Returns:
|
|
统计信息字典
|
|
"""
|
|
query = self.db.query(self.model)
|
|
if project_id:
|
|
query = query.filter(self.model.project_id == project_id)
|
|
|
|
total_tasks = query.count()
|
|
pending_tasks = query.filter(self.model.status == TaskStatus.PENDING).count()
|
|
running_tasks = query.filter(self.model.status == TaskStatus.RUNNING).count()
|
|
completed_tasks = query.filter(self.model.status == TaskStatus.COMPLETED).count()
|
|
failed_tasks = query.filter(self.model.status == TaskStatus.FAILED).count()
|
|
|
|
return {
|
|
"total": total_tasks,
|
|
"pending": pending_tasks,
|
|
"running": running_tasks,
|
|
"completed": completed_tasks,
|
|
"failed": failed_tasks,
|
|
"success_rate": (completed_tasks / total_tasks * 100) if total_tasks > 0 else 0
|
|
}
|
|
|
|
def get_recent_tasks(self, limit: int = 10) -> List[Task]:
|
|
"""
|
|
获取最近的任务
|
|
|
|
Args:
|
|
limit: 返回数量限制
|
|
|
|
Returns:
|
|
最近的任务列表
|
|
"""
|
|
return self.db.query(self.model).order_by(
|
|
desc(self.model.created_at)
|
|
).limit(limit).all()
|
|
|
|
def get_tasks_by_date_range(self, start_date, end_date, project_id: str = None) -> List[Task]:
|
|
"""
|
|
根据日期范围获取任务
|
|
|
|
Args:
|
|
start_date: 开始日期
|
|
end_date: 结束日期
|
|
project_id: 项目ID,如果为None则查询所有项目
|
|
|
|
Returns:
|
|
任务列表
|
|
"""
|
|
query = self.db.query(self.model).filter(
|
|
self.model.created_at >= start_date,
|
|
self.model.created_at <= end_date
|
|
)
|
|
|
|
if project_id:
|
|
query = query.filter(self.model.project_id == project_id)
|
|
|
|
return query.order_by(desc(self.model.created_at)).all()
|
|
|
|
def get_long_running_tasks(self, max_duration_hours: int = 2) -> List[Task]:
|
|
"""
|
|
获取长时间运行的任务
|
|
|
|
Args:
|
|
max_duration_hours: 最大运行时间(小时)
|
|
|
|
Returns:
|
|
长时间运行的任务列表
|
|
"""
|
|
from datetime import datetime, timedelta
|
|
cutoff_time = datetime.utcnow() - timedelta(hours=max_duration_hours)
|
|
|
|
return self.db.query(self.model).filter(
|
|
self.model.status == TaskStatus.RUNNING,
|
|
self.model.started_at <= cutoff_time
|
|
).all()
|
|
|
|
def cleanup_old_tasks(self, days: int = 30) -> int:
|
|
"""
|
|
清理旧任务
|
|
|
|
Args:
|
|
days: 保留天数
|
|
|
|
Returns:
|
|
删除的任务数量
|
|
"""
|
|
from datetime import datetime, timedelta
|
|
cutoff_date = datetime.utcnow() - timedelta(days=days)
|
|
|
|
deleted_count = self.db.query(self.model).filter(
|
|
self.model.created_at < cutoff_date,
|
|
self.model.status.in_([TaskStatus.COMPLETED, TaskStatus.FAILED])
|
|
).delete(synchronize_session=False)
|
|
|
|
self.db.commit()
|
|
return deleted_count |