feat(ingest): 采集任务状态跟踪(ingest_jobs),解决 fire-and-forget 不可观测

- 新表 ingest_jobs(迁移 0019): id UUID/task/params JSONB/
  status(pending|running|success|failed,CheckConstraint)/
  result JSONB(统计摘要)/error/created_at/started_at/finished_at
- POST /ingest/bzzoiro: 启动后台前创建 pending job,响应返回 job_id;
  仍 require_admin。后台 _run_bzzoiro 流转 running→success/failed,
  result 按子任务(events/standings/stats)记录摘要(errors 截断 10 条)
- _update_job 尽力而为: 状态更新失败只记日志,绝不拖垮采集主流程;
  与 IngestFailure 死信独立(行级 vs 任务级,可同时存在)
- 新增 admin 端点(挂 /api/v1/admin 路由,路由级 require_admin):
  GET /admin/ingest/jobs/{job_id} 与 GET /admin/ingest/jobs?limit&status
- 前端采集页: 提交后凭 job_id 3 秒轮询,终态展示结果摘要/失败原因;
  无 job_id 时回退旧的 30 秒盲等 + 系统日志提示
- 测试 11 项: 建 job+job_id 契约、非法 task 422、成功/失败/all 流转、
  update 失败不拖垮采集、部分失败仍 success、admin 端点 200/404/列表、
  结构守护(job 路由在 admin 路由且带 require_admin)
- 禁止项确认: 未动分批 UoW、BzzoiroSource、死信与 Bronze 写入;
  docs(01/03/05/07/README)同步 13 张表与端点说明
This commit is contained in:
WorkBuddy
2026-09-21 21:19:21 +08:00
parent 6bdb1f8ae6
commit 983363dab7
13 changed files with 666 additions and 36 deletions
+19 -1
View File
@@ -190,9 +190,27 @@ Base URL: `http://localhost:8000` · 交互式文档: `/docs`(Swagger)与 `/redo
| `season` | 当前赛季 | standings 赛季,如 `"2026-2027"` |
| `limit` | 100 | stats 回填单次最大比赛数(1500) |
- 响应含每联赛 `inserted`/`updated`/`errors` 统计
- 响应:`{"ok": true, "job_id": "<uuid>", "message": "……"}`,`job_id` 用于查询任务状态
- `task=stats` 只补空字段、不创建比赛(xG/射门/控球等统计回填)
### `GET /api/v1/admin/ingest/jobs/{job_id}`(需管理员)
查询一次采集任务的状态(`ingest_jobs` 表,任务级可观测性):
```json
{"id": "…", "task": "standings", "params": {"leagues": ["E0"]},
"status": "success", "result": {"total_upserted": 20, "errors": []},
"error": null, "created_at": "…", "started_at": "…", "finished_at": "…"}
```
- `status` 取值:`pending`(已创建未开始)/ `running` / `success` / `failed`
- 管理端采集页提交后凭 `job_id` 轮询本端点直至终态
-`ingest_failures` 死信独立:死信记录单条管线抓取失败(行级),job 记录整次任务结果
### `GET /api/v1/admin/ingest/jobs?limit=20&status=`(需管理员)
列出最近采集任务(最新在前),可按 `status` 过滤,`limit` 1100。
> 历史版本曾有独立的 understat(xG)与 injuries(伤停)采集端点,
> 已随数据源收敛为 bzzoiro 唯一来源而移除。