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

@@ -1,6 +1,6 @@
# 内容导入契约
更新时间2026-06-29
更新时间2026-07-12
## 结论
@@ -98,6 +98,24 @@ npm --workspace @tiku-saas/worker run imports:once
前端提交异步导入后不要重复同步执行同一 job只需要轮询 `GET /api/tenant-content/imports` 并用 `GET /api/tenant-content/imports/issues` 展示问题行。worker 会按 `attempt_count/max_attempts` 记录重试,失败时写入 `errorMessage` 和审计日志。
异步 worker 使用数据库持久 lease不能只依赖进程内状态
- claim 是单条 `UPDATE ... FROM (SELECT ... FOR UPDATE SKIP LOCKED)`,多实例不会领取同一个 job。
- 每次 claim 都生成新的 `lease_token` fencing token并写入 `locked_by``locked_at``lease_expires_at``last_heartbeat_at`
- 长任务按 `WORKER_IMPORT_HEARTBEAT_INTERVAL_MS` 续租;该值必须小于 `WORKER_IMPORT_LEASE_SECONDS` 的一半。
- worker 崩溃后,其他实例可在 lease 过期后重新领取,并原子增加 `attempt_count`
- 完成、失败和重试提交都必须同时匹配 job、`status=importing`、未过期 lease 和 `lease_token`。旧实例丢失 lease 后,其导入事务整体回滚,不能覆盖接管者的结果或审计。
- attempt 已耗尽的过期 job 会直接转为 `failed`,不会额外执行一次。
生产建议先保持默认配置:
```env
WORKER_IMPORT_LEASE_SECONDS=120
WORKER_IMPORT_HEARTBEAT_INTERVAL_MS=30000
```
lease 应覆盖数据库短暂抖动,但不应长到显著拖慢崩溃恢复;调整时必须同时运行 `test:worker:imports` 和 production readiness。
## 模板、字段映射和导入后复检
租户后台前端不要把导入字段写死在页面里。导入页初始化时先读取字段映射,下载模板时调用模板接口: