116 lines
3.5 KiB
Python
116 lines
3.5 KiB
Python
from datetime import datetime, timezone
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException, status
|
|
from sqlalchemy import func, select
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from app.dependencies import get_db, get_current_user
|
|
from app.models.user import User
|
|
from app.models.project import Project
|
|
from app.models.generation_record import GenerationRecord
|
|
from app.schemas.project import ProjectCreate, ProjectOut
|
|
from app.services.resource_accounting_service import soft_delete_generation_record_resources
|
|
from app.services.video_upscale.guard_service import assert_no_recoverable_failed_upscale_tasks
|
|
from app.utils.id_gen import generate_id
|
|
|
|
router = APIRouter(prefix="/projects", tags=["projects"])
|
|
|
|
|
|
@router.get("", response_model=list[ProjectOut])
|
|
async def list_projects(
|
|
current_user: User = Depends(get_current_user),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
result = await db.execute(
|
|
select(Project)
|
|
.where(
|
|
Project.user_id == current_user.id,
|
|
Project.deleted_at.is_(None),
|
|
)
|
|
.order_by(Project.created_at.desc())
|
|
)
|
|
return result.scalars().all()
|
|
|
|
|
|
@router.post("", response_model=ProjectOut)
|
|
async def create_project(
|
|
req: ProjectCreate,
|
|
current_user: User = Depends(get_current_user),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
project = Project(
|
|
id=generate_id(),
|
|
user_id=current_user.id,
|
|
name=req.name,
|
|
industry=req.industry,
|
|
)
|
|
db.add(project)
|
|
await db.flush()
|
|
return project
|
|
|
|
|
|
@router.delete("/{project_id}")
|
|
async def delete_project(
|
|
project_id: str,
|
|
current_user: User = Depends(get_current_user),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
result = await db.execute(
|
|
select(Project).where(
|
|
Project.id == project_id,
|
|
Project.user_id == current_user.id,
|
|
Project.deleted_at.is_(None),
|
|
)
|
|
.limit(1)
|
|
)
|
|
project = result.scalar_one_or_none()
|
|
if not project:
|
|
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="项目不存在")
|
|
|
|
generating_count = (
|
|
await db.execute(
|
|
select(func.count(GenerationRecord.id)).where(
|
|
GenerationRecord.project_id == project_id,
|
|
GenerationRecord.user_id == current_user.id,
|
|
GenerationRecord.status == "generating",
|
|
GenerationRecord.deleted_at.is_(None),
|
|
)
|
|
)
|
|
).scalar() or 0
|
|
if generating_count > 0:
|
|
raise HTTPException(status_code=400, detail="当前项目下存在生成中任务,暂不能删除")
|
|
|
|
records_result = await db.execute(
|
|
select(GenerationRecord).where(
|
|
GenerationRecord.project_id == project_id,
|
|
GenerationRecord.user_id == current_user.id,
|
|
GenerationRecord.deleted_at.is_(None),
|
|
)
|
|
)
|
|
records = list(records_result.scalars().all())
|
|
record_ids = [record.id for record in records]
|
|
await assert_no_recoverable_failed_upscale_tasks(
|
|
db,
|
|
generation_record_ids=record_ids,
|
|
)
|
|
now = datetime.now(timezone.utc)
|
|
|
|
project.deleted_at = now
|
|
for record in records:
|
|
record.deleted_at = now
|
|
|
|
freed_size_bytes = await soft_delete_generation_record_resources(
|
|
db,
|
|
record_ids,
|
|
deleted_at=now,
|
|
)
|
|
|
|
await db.flush()
|
|
return {
|
|
"message": "ok",
|
|
"project_id": project_id,
|
|
"deleted": True,
|
|
"deleted_records": len(record_ids),
|
|
"freed_size_bytes": freed_size_bytes,
|
|
}
|