Files
video-gen/video-gen-api/app/services/video_upscale/guard_service.py
T
2026-07-16 15:02:03 +08:00

62 lines
2.2 KiB
Python

from __future__ import annotations
import os
from collections.abc import Iterable
from fastapi import HTTPException
from sqlalchemy import or_, select
from sqlalchemy.ext.asyncio import AsyncSession
from app.enums.video_upscale import VideoUpscaleTaskStatus
from app.models.video_upscale_task import VideoUpscaleTask
async def assert_no_recoverable_failed_upscale_tasks(
db: AsyncSession,
chat_task_ids: Iterable[str] | None = None,
*,
generation_record_ids: Iterable[str] | None = None,
) -> None:
"""阻止删除仍保留本地源视频、可由管理员人工恢复的超分失败任务。"""
chat_ids = list(dict.fromkeys(str(item) for item in (chat_task_ids or []) if item))
record_ids = list(dict.fromkeys(str(item) for item in (generation_record_ids or []) if item))
if not chat_ids and not record_ids:
return
owner_conditions = []
if chat_ids:
owner_conditions.append(VideoUpscaleTask.chat_generation_task_id.in_(chat_ids))
if record_ids:
owner_conditions.append(VideoUpscaleTask.generation_record_id.in_(record_ids))
result = await db.execute(
select(
VideoUpscaleTask.chat_generation_task_id,
VideoUpscaleTask.generation_record_id,
VideoUpscaleTask.source_local_path,
).where(
or_(*owner_conditions),
VideoUpscaleTask.status == VideoUpscaleTaskStatus.FAILED.value,
VideoUpscaleTask.source_local_path.isnot(None),
VideoUpscaleTask.source_deleted_at.is_(None),
)
)
recoverable = []
for chat_task_id, generation_record_id, source_local_path in result.all():
if source_local_path and os.path.isfile(str(source_local_path)):
recoverable.append(
{
"owner_type": "chat_generation_task" if chat_task_id else "generation_record",
"owner_id": str(chat_task_id or generation_record_id),
}
)
if recoverable:
raise HTTPException(
status_code=409,
detail={
"message": "当前生成任务异常暂不能删除",
"items": recoverable,
"task_count": len(recoverable),
},
)