64 lines
2.1 KiB
Python
64 lines
2.1 KiB
Python
import json
|
|
from pathlib import Path
|
|
|
|
from fastapi import APIRouter, HTTPException, status
|
|
from fastapi.responses import FileResponse, JSONResponse
|
|
|
|
from app.config import get_settings
|
|
from app.models.jobs import JobResponse
|
|
from app.services.jobs import get_job, get_job_record
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
def _artifact_path(job_id: str) -> Path:
|
|
record = get_job_record(job_id)
|
|
if record is None:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail={"code": "JOB_NOT_FOUND", "detail": "Job not found"},
|
|
)
|
|
if record.get("status") != "done":
|
|
raise HTTPException(
|
|
status_code=status.HTTP_409_CONFLICT,
|
|
detail={"code": "JOB_NOT_READY", "detail": "Job is not finished yet"},
|
|
)
|
|
uri = (record.get("result") or {}).get("uri")
|
|
if not uri:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail={"code": "ARTIFACT_NOT_FOUND", "detail": "Job has no artifact URI"},
|
|
)
|
|
path = Path(uri).resolve()
|
|
root = get_settings().jobs_output_path.resolve()
|
|
if root not in path.parents and path != root:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_403_FORBIDDEN,
|
|
detail={"code": "ARTIFACT_FORBIDDEN", "detail": "Artifact path is outside jobs output"},
|
|
)
|
|
if not path.is_file():
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail={"code": "ARTIFACT_MISSING", "detail": f"Artifact file not found: {path.name}"},
|
|
)
|
|
return path
|
|
|
|
|
|
@router.get("/{job_id}", response_model=JobResponse)
|
|
def read(job_id: str) -> JobResponse:
|
|
job = get_job(job_id)
|
|
if job is None:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail={"code": "JOB_NOT_FOUND", "detail": "Job not found"},
|
|
)
|
|
return job
|
|
|
|
|
|
@router.get("/{job_id}/artifact")
|
|
def read_artifact(job_id: str):
|
|
path = _artifact_path(job_id)
|
|
if path.suffix.lower() == ".json":
|
|
return JSONResponse(content=json.loads(path.read_text(encoding="utf-8")))
|
|
return FileResponse(path)
|