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:
@@ -20,7 +20,7 @@
|
||||
│ │ │ └─ aggregator 终裁(强模型) │ │
|
||||
│ │ └────────────┘ │ events / standings │ │
|
||||
│ ┌──┴──────────────┴──┐ │ /stats 三条管线 │ │
|
||||
│ │ PostgreSQL (12 张表)│ └───────────────────┘ │
|
||||
│ │ PostgreSQL (13 张表)│ └───────────────────┘ │
|
||||
│ └────────────────────┘ httpx → 外部 API │
|
||||
└─────────────────────────────────────────────────────┘
|
||||
```
|
||||
@@ -70,7 +70,7 @@ Profeto/
|
||||
│ │ └── schedules.py # 定时任务 + 死信重试(router 级鉴权)
|
||||
│ ├── db/
|
||||
│ │ ├── base.py # async engine + get_db/get_db_read
|
||||
│ │ ├── models.py # 12 张表 ORM
|
||||
│ │ ├── models.py # 13 张表 ORM
|
||||
│ │ ├── repositories.py # 仓储层
|
||||
│ │ └── unit_of_work.py # 事务边界
|
||||
│ ├── data/
|
||||
|
||||
+19
-1
@@ -190,9 +190,27 @@ Base URL: `http://localhost:8000` · 交互式文档: `/docs`(Swagger)与 `/redo
|
||||
| `season` | 当前赛季 | standings 赛季,如 `"2026-2027"` |
|
||||
| `limit` | 100 | stats 回填单次最大比赛数(1–500) |
|
||||
|
||||
- 响应含每联赛 `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` 1–100。
|
||||
|
||||
> 历史版本曾有独立的 understat(xG)与 injuries(伤停)采集端点,
|
||||
> 已随数据源收敛为 bzzoiro 唯一来源而移除。
|
||||
|
||||
|
||||
+3
-2
@@ -65,7 +65,7 @@
|
||||
|
||||
## 数据库 Schema
|
||||
|
||||
12 张表:核心业务表 5 张见下方 DDL,其余 7 张(积分榜/配置/调度/治理)见后文表格。
|
||||
12 张业务/配置表 + 1 张任务状态表(`ingest_jobs`):核心业务表 5 张见下方 DDL,其余见后文表格。
|
||||
|
||||
```sql
|
||||
-- 联赛
|
||||
@@ -146,13 +146,14 @@ CREATE TABLE predictions (
|
||||
);
|
||||
```
|
||||
|
||||
其余 7 张表(DDL 略,详见 `src/db/models.py` 与 alembic 迁移):
|
||||
其余 8 张表(DDL 略,详见 `src/db/models.py` 与 alembic 迁移):
|
||||
|
||||
| 表 | 状态 | 用途 |
|
||||
|---|---|---|
|
||||
| `standings` | 已启用 | 联赛积分榜快照,按 `(league_id, season, team_id)` upsert,同联赛同赛季只保留最新快照;含排名/战绩/进失球/积分/分区(zone) |
|
||||
| `app_settings` | 已启用 | 后台运行时设置(如数据源 API Key),读取时优先于 `.env` 默认值 |
|
||||
| `schedules` | 已启用 | 定时采集任务配置(task/cron/leagues/enabled),供内置调度器执行 |
|
||||
| `ingest_jobs` | 已启用 | 采集任务状态:POST ingest 创建 pending,后台流转 running→success/failed;result 存统计摘要,供 admin 轮询(任务级,与死信互补) |
|
||||
| `raw_events` | 预留未启用 | Bronze 层原始事件存档;规划中用于重放与审计 |
|
||||
| `ingest_failures` | 已启用 | 采集失败死信:bzzoiro 三条管线(events/standings/stats)抓取失败时写入,admin 后台可查看与重试 |
|
||||
| `data_quality_checks` | 预留未启用 | 数据质量检查结果;规划中定时检查比赛/统计/积分榜完整性 |
|
||||
|
||||
@@ -129,7 +129,8 @@ Profeto/
|
||||
│ ├── 0003_injuries.py
|
||||
│ ├── 0004_snapshot_and_constraints.py
|
||||
│ ├── 0005_prediction_status_and_stats_provenance.py
|
||||
│ └── 0006_schema_model_drift_cleanup.py
|
||||
│ ├── 0006_schema_model_drift_cleanup.py
|
||||
│ └── …… (共 19 个迁移,最新 0019_ingest_jobs)
|
||||
├── tests/ # 测试
|
||||
│ ├── test_core.py # 核心逻辑测试
|
||||
│ └── test_agents.py # 多 agent 测试
|
||||
|
||||
Reference in New Issue
Block a user