新增 ingest_jobs 表(UUID/task/params/status/result/error/时间戳),
POST /ingest/bzzoiro 启动前插入 job(pending)→ 后台 running → success/failed,
响应新增 job_id(兼容原 message)。
Admin GET /admin/ingest/jobs/{id} 与 /admin/ingest/jobs?limit= 只读查询;
Collection 页提交后轮询 job 至终态,展示真实 result/error 汇总。
迁移 0019_ingest_jobs + 分批 get_uow/BzzoiroSource/IngestFailure 不变。
全量测试 270 通过。
56 lines
1.7 KiB
Python
56 lines
1.7 KiB
Python
"""后台管理:采集任务状态查询(只读)。
|
|
|
|
GET /api/v1/admin/ingest/jobs/{job_id} — 单任务详情
|
|
GET /api/v1/admin/ingest/jobs?limit=N — 最近任务列表(默认 20)
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException, Query
|
|
from sqlalchemy import desc, select
|
|
|
|
from src.api.deps import require_admin
|
|
from src.api.schemas import IngestJobOut
|
|
from src.db.base import AsyncSession, get_db_read
|
|
from src.db.models import IngestJob
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
router = APIRouter(prefix="/api/v1/admin", tags=["admin"], dependencies=[Depends(require_admin)])
|
|
|
|
|
|
@router.get("/ingest/jobs/{job_id}", response_model=IngestJobOut)
|
|
async def get_ingest_job(job_id: str, db: AsyncSession = Depends(get_db_read)):
|
|
"""查询单个采集任务状态。"""
|
|
job = await db.get(IngestJob, job_id)
|
|
if job is None:
|
|
raise HTTPException(404, f"采集任务不存在: {job_id}")
|
|
return _job_to_out(job)
|
|
|
|
|
|
@router.get("/ingest/jobs", response_model=list[IngestJobOut])
|
|
async def list_ingest_jobs(
|
|
limit: int = Query(20, ge=1, le=100, description="返回条数"),
|
|
db: AsyncSession = Depends(get_db_read),
|
|
):
|
|
"""查询最近采集任务(最新在前)。"""
|
|
rows = (
|
|
await db.execute(select(IngestJob).order_by(desc(IngestJob.created_at)).limit(limit))
|
|
).scalars().all()
|
|
return [_job_to_out(j) for j in rows]
|
|
|
|
|
|
def _job_to_out(job: IngestJob) -> IngestJobOut:
|
|
return IngestJobOut(
|
|
id=job.id,
|
|
task=job.task,
|
|
params=job.params or {},
|
|
status=job.status,
|
|
result=job.result,
|
|
error=job.error,
|
|
created_at=job.created_at,
|
|
started_at=job.started_at,
|
|
finished_at=job.finished_at,
|
|
)
|