feat: establish production SaaS foundation

This commit is contained in:
Codex
2026-07-12 19:26:57 +08:00
parent 1c2ce38cea
commit 39f7332f33
219 changed files with 20647 additions and 2628 deletions

View File

@@ -0,0 +1,42 @@
# Import worker 持久 lease 验证报告
更新时间2026-07-12
## 结论
`content_import_jobs` 已具备多实例和进程重启所需的持久 lease 与 fencing 语义。验证只在专用测试库 `127.0.0.1:55432` 执行,没有连接生产环境。
## 实现边界
- migration `202607120016_content_import_job_leases.sql` 增加 `lease_token``lease_expires_at``last_heartbeat_at`、一致性约束和 pending/expired 部分索引。
- claim 使用原子 `SKIP LOCKED`,可同时领取 ready pending job 和 lease 已过期的 importing job。
- 每次 claim 只增加一次 `attempt_count` 并生成新 token失败调度只写 `next_attempt_at`,不会重复增加 attempt。
- worker 在执行期间续租;续租、完成、失败和重试都要求 token 匹配且 lease 未过期。
- API executor 的业务写入和终态更新处于同一事务。fencing 校验失败会回滚题目、版本、集合绑定、item 和 audit 写入。
- 最后一次 attempt 的 lease 过期后由 claim/reaper 路径直接标记 failed避免第 `max_attempts + 1` 次执行。
## 动态覆盖
`scripts/import-worker-integration-test.js` 在 destructive-test database guard 后验证:
1. 两个并发 worker 对三个 job 原子 claim没有重复领取。
2. 心跳推进 `last_heartbeat_at` 并延长 `lease_expires_at`
3. 模拟崩溃后,过期 job 被新 worker 接管token 旋转且 attempt 从 1 变为 2。
4. 旧 token 的执行在业务写入前被拒绝,旧 token 的失败提交也不能覆盖新 lease。
5. 新 lease 可完成 job终态清空 lease 字段并保持准确 attempt。
6. retry 保持 pending、持久 `next_attempt_at`,再次 claim 才增加 attempt。
7. 最后 attempt 过期后进入 failed不再重新执行。
## 验证命令
```bash
npm run check:worker
npm run check:api
npm run build:worker
DATABASE_URL=postgresql://postgres:postgres@127.0.0.1:55432/postgres \
node scripts/import-worker-integration-test.js \
--confirm=SMOKE_SEED_LOCAL_OR_CI_ONLY
node scripts/production-readiness-check-test.js
```
完整 worker integration 会先跑 smoke seed执行时必须明确指向允许 destructive tests 的本地/CI 数据库。