Files

64 lines
2.1 KiB
Python
Raw Permalink Normal View History

import json
from datetime import datetime, timezone
from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.orm import Session
from app.database import get_db
from app.models import JobModel
from app.schemas import EntityResponse, Job, JobStatus, ListResponse
router = APIRouter(prefix='/jobs', tags=['jobs'])
def _to_job(m: JobModel) -> Job:
return Job(
id=m.id, type=m.type, status=m.status,
progress=m.progress, message=m.message, error=m.error,
payload=json.loads(m.payload_json or '{}'),
result=json.loads(m.result_json or 'null'),
created_at=m.created_at,
started_at=m.started_at,
finished_at=m.finished_at,
)
@router.get('', response_model=ListResponse[Job])
def list_jobs(
status: JobStatus | None = Query(default=None),
type: str | None = Query(default=None),
db: Session = Depends(get_db),
):
q = db.query(JobModel)
if status:
q = q.filter(JobModel.status == status)
if type:
q = q.filter(JobModel.type == type)
rows = q.order_by(JobModel.created_at.desc()).all()
return ListResponse(count=len(rows), items=[_to_job(r) for r in rows])
@router.get('/{job_id}', response_model=EntityResponse[Job])
def get_job(job_id: str, db: Session = Depends(get_db)):
row = db.query(JobModel).filter(JobModel.id == job_id).first()
if not row:
raise HTTPException(status_code=404, detail='Job not found')
return EntityResponse(item=_to_job(row))
@router.post('/{job_id}/cancel', response_model=EntityResponse[Job])
def cancel_job(job_id: str, db: Session = Depends(get_db)):
row = db.query(JobModel).filter(JobModel.id == job_id).first()
if not row:
raise HTTPException(status_code=404, detail='Job not found')
if row.status not in ('pending', 'running'):
raise HTTPException(
status_code=409,
detail=f'Cannot cancel job with status {row.status!r}',
)
row.status = 'cancelled'
row.finished_at = datetime.now(timezone.utc)
db.commit()
db.refresh(row)
return EntityResponse(item=_to_job(row))