feat(db): wire jobs router to SQLAlchemy, add cancel endpoint
CI / basic-check (push) Has been cancelled

This commit is contained in:
2026-08-06 16:12:34 +00:00
parent 76886b93d3
commit 54976814fc
+53 -9
View File
@@ -1,19 +1,63 @@
from fastapi import APIRouter, HTTPException
import json
from datetime import datetime, timezone
from app.schemas import EntityResponse, Job, ListResponse
from app.services.store import JOBS
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() -> ListResponse[Job]:
return ListResponse(count=len(JOBS), items=JOBS)
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) -> EntityResponse[Job]:
for item in JOBS:
if item.id == job_id:
return EntityResponse(item=item)
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))