from fastapi import APIRouter, Depends, HTTPException, Query from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select from ..models.database import get_session from ..models.tables import Job, Video, JobStatus from ..models.schemas import JobOut, JobListOut, ProcessResponse router = APIRouter() @router.get("", response_model=JobListOut) async def list_jobs(session: AsyncSession = Depends(get_session)): result = await session.execute(select(Job).order_by(Job.created_at.desc())) jobs = result.scalars().all() return JobListOut(jobs=[JobOut.model_validate(j) for j in jobs]) @router.get("/{job_id}", response_model=JobOut) async def get_job(job_id: int, session: AsyncSession = Depends(get_session)): result = await session.execute(select(Job).where(Job.id == job_id)) job = result.scalar_one_or_none() if not job: raise HTTPException(404, "Job not found") return JobOut.model_validate(job) @router.post("/{job_id}/cancel", response_model=ProcessResponse) async def cancel_job(job_id: int, session: AsyncSession = Depends(get_session)): result = await session.execute(select(Job).where(Job.id == job_id)) job = result.scalar_one_or_none() if not job: raise HTTPException(404, "Job not found") if job.status not in (JobStatus.pending.value, JobStatus.running.value): raise HTTPException(400, f"Cannot cancel job in status '{job.status}'") job.status = JobStatus.failed.value job.error_message = "Cancelled by user" await session.commit() video_result = await session.execute(select(Video).where(Video.id == job.video_id)) video = video_result.scalar_one_or_none() if video: if job.job_type == "process": video.status = "uploaded" elif job.job_type == "generate": video.status = "review" video.error_message = None await session.commit() return ProcessResponse(job_id=job.id, message="Job cancelled")