tnt-group / backend /app /api /common.py
titusgiap's picture
perf: queue theo loại + code-split FE + streaming upload cho nhiều user
3370310
Raw
History Blame Contribute Delete
2.36 kB
"""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")
# inline (KHÔNG attachment) -> trình duyệt render video/ảnh trực tiếp trong <video>.
# Nút tải vẫn hoạt động nhờ thuộc tính `download` phía frontend.
return FileResponse(full, filename=os.path.basename(full),
content_disposition_type="inline")