| """Endpoint dùng chung: trạng thái job, tải file kết quả.""" |
|
|
| from __future__ import annotations |
|
|
| import os |
| from urllib.parse import quote |
|
|
| from fastapi import APIRouter, HTTPException |
| from fastapi.responses import FileResponse |
|
|
| from ..core.files import session_dir, delete_session |
| from ..core.jobs import jobs |
|
|
| router = APIRouter(prefix="/api", tags=["common"]) |
|
|
|
|
| @router.delete("/sessions/{sid}") |
| def drop_session(sid: str): |
| """Xoá phiên tạm sau khi user đã tải kết quả về máy (không bắt buộc).""" |
| return {"deleted": delete_session(sid), "session": sid} |
|
|
|
|
| @router.get("/jobs/{job_id}") |
| def job_status(job_id: str): |
| job = jobs.get(job_id) |
| if not job: |
| raise HTTPException(404, "job không tồn tại") |
| return job.to_dict() |
|
|
|
|
| @router.get("/queue/stats") |
| def queue_stats(): |
| """Số liệu hàng đợi: số job đang chạy/chờ theo loại + tổng job trong bộ nhớ.""" |
| return jobs.stats() |
|
|
|
|
| @router.post("/jobs/{job_id}/cancel") |
| def job_cancel(job_id: str): |
| jobs.cancel(job_id) |
| return {"ok": True} |
|
|
|
|
| @router.get("/sessions/{sid}/inputs") |
| def list_inputs(sid: str): |
| """Liệt kê video trong thư mục inputs của phiên (dùng khi đẩy từ Down list).""" |
| d = os.path.join(session_dir(sid), "inputs") |
| if not os.path.isdir(d): |
| return {"session": sid, "files": []} |
| out = [] |
| for name in sorted(os.listdir(d)): |
| full = os.path.join(d, name) |
| if os.path.isfile(full): |
| out.append({ |
| "file": f"inputs/{name}", |
| "name": name, |
| "size": os.path.getsize(full), |
| "url": f"/api/files/{sid}/inputs/{quote(name)}", |
| }) |
| return {"session": sid, "files": out} |
|
|
|
|
| @router.get("/files/{sid}/{path:path}") |
| def get_file(sid: str, path: str): |
| base = os.path.abspath(session_dir(sid)) |
| full = os.path.abspath(os.path.join(base, path)) |
| if not full.startswith(base) or not os.path.exists(full): |
| raise HTTPException(404, "file không tồn tại") |
| |
| |
| return FileResponse(full, filename=os.path.basename(full), |
| content_disposition_type="inline") |
|
|