feat(jobs): 增加后台任务运行时

This commit is contained in:
2026-07-08 17:02:51 +08:00
parent 69f50ea1f5
commit ba999c9322
14 changed files with 575 additions and 2 deletions

View File

@@ -135,6 +135,18 @@ DevTask 没有"已完成"状态,"已提测"就是终态——开发交付完
- V2.3AppData 保存成功后触发关系表同步,让快读路径保持新鲜;同步失败只记日志,不阻塞用户保存。
- V2.4:领域 CRUD 成为主写入路径AppData 写桥保留给历史数据和回滚兜底。不要恢复业务 localStorage 缓存,避免线上部署后出现多端数据分叉。
## Background Job Runtime Layer (V2.6)
V2.6 introduces a database-backed background job runtime for server-side refresh work that must not depend on a user opening a page.
- Storage: `background_jobs` stores `type`, `payload`, `dedupe_key`, `status`, `attempts`, `max_attempts`, `available_at`, `locked_by`, `locked_until`, and `last_error`.
- Dedupe: active jobs (`queued` / `running`) are unique by `(type, dedupe_key)` when `dedupe_key` is present. Services still check first and recover from unique conflicts to stay idempotent under concurrent enqueue.
- Lease: `JobLockService.claimNext()` uses `FOR UPDATE SKIP LOCKED` and treats expired `running` rows as claimable, so a crashed worker can be recovered by a later worker.
- Retry: failed handlers are requeued while `attempts < max_attempts`; terminal failures keep `last_error` and move to `failed`.
- Worker boundary: `BackgroundJobWorker` is a small handler registry and single-job runner. Domain modules register typed handlers and only write through their own services.
This runtime is intentionally DB-backed first. Redis is already available in deployment, but V2.6 jobs need transactional dedupe with domain writes more than high-throughput queue semantics.
## 生产部署层2026-07-01
当前仓库已补齐云服务器生产部署基线:

View File

@@ -578,3 +578,17 @@
- 分区键进入每次领域写入,能维持 V2.2 分区表设计的查询边界。
- AppData fallback 让迁移可回滚、可兼容旧数据,但不再制造长期双事实源。
- RBAC/配置表会影响权限模型和管理流程单独成阶段更安全V2.4.5 只收口当前高频业务写入,避免为了“全收口”临时设计不稳的权限 schema。
## 45. V2.6 后台任务先采用 PostgreSQL Lease 队列
**问题**小宝风险摘要、AI 解读和后续通知都需要在用户不打开页面时后台刷新。直接把这些逻辑放在页面 effect 中会导致无人访问时数据不更新;直接引入 Redis queue 又会增加一套可靠性、幂等和迁移运维面。
**决策**
- 新增 `background_jobs` 表和 `JobsModule`,作为 V2.6 后台任务运行时。
- Job 行包含 `type``payload``dedupe_key``status``attempts``max_attempts``available_at``locked_by``locked_until``last_error`
- 同一 `type + dedupe_key``queued/running` 状态下唯一;服务层先查 active job遇到并发唯一冲突再回读保证 enqueue 幂等。
- Worker claim 使用数据库事务、`FOR UPDATE SKIP LOCKED` 和 lease 时间;`running``locked_until` 过期的 job 可以被新 worker 回收。
- Handler 失败时按 `attempts < max_attempts` 重回 `queued` 并设置下一次 `available_at`;达到上限后进入 `failed`,只记录错误,不修改业务实体。
- `BackgroundJobWorker` 只负责 handler 注册和单次执行,业务副作用仍放在各领域 service 内,避免队列层知道小宝、通知或审计细节。
**理由**PostgreSQL 队列足够支撑 V2.6 的低频后台刷新,同时能和领域写入共享事务边界、唯一约束和迁移流程。等 V2.7 通知或更高吞吐任务落地后,如确实需要 Redis/专用队列,再通过同一 `JobsService` 接口替换底层实现,而不是现在提前引入第二套事实源。

View File

@@ -1,8 +1,8 @@
# 开发路线图
## 当前阶段V2.4领域 CRUD 主写迁移完成
## 当前阶段V2.6大数据性能增强 + 小宝后台化(进行中)
V2.4 高增长和核心业务领域从“AppData 主写 + 关系表同步副本”推进到“领域 CRUD 主写关系表 + AppData 兼容/迁移兜底”。V2.2 快读 API 和 V2.3 AppData 写后同步继续保留,但它们现在是兼容基础设施,不再是已迁移领域的数据新鲜度主链路
V2.4 已完成高增长和核心业务领域从“AppData 主写 + 关系表同步副本”到“领域 CRUD 主写关系表 + AppData 兼容/迁移兜底”的迁移。V2.6 当前聚焦大数据 fixture、热查询预算、后台 job runtime以及把小宝风险摘要和 AI 解读从页面触发迁到服务端后台
### 当前状态快照2026-07-08
@@ -14,10 +14,16 @@ V2.4 将高增长和核心业务领域从“AppData 主写 + 关系表同步副
- 需求池已切到服务端分页、搜索、筛选、排序,不再要求加载全量 AppData 文档。
- `packages/shared` 状态契约已统一为当前业务状态机。
- V2.4.5 保守边界:成员身份写 `users`;部门、角色、密码规则、加班原因暂留 AppData 配置,等待后续 RBAC/配置表阶段。
- V2.6.1 已新增 deterministic large-data fixture、HTTP performance harness 和性能预算文档。
- V2.6.2 已新增 hot query explain/index audit 脚本、热查询索引迁移和 `docs/performance-hot-queries.md`
- V2.6.3 已新增 PostgreSQL-backed `background_jobs` 运行时、去重/lease/retry 语义和 jobs 单元测试。
### 已完成(按时间倒序)
**2026-07-08**
- V2.6.3 added DB-backed background jobs with active dedupe keys, lease-based claiming, expired lock recovery, retry/terminal-failure handling, and a small handler worker.
- V2.6.2 added `perf:explain`, hot query explain targets, index audit documentation, and V2.6 hot-path indexes for workspace, Xiaobao warning/dirty queues, project/version lists, and evidence scans.
- V2.6.1 added deterministic small/medium/large fixture generation, `perf:check`, and `docs/performance.md` for hot API p50/p95 budgets.
- V2.4.0 completed shared domain status contract alignment for Requirement, VersionPlan, DevTask, TestCase, Bug, and Version.
- V2.4.1 switched Product / Project / Version root mutations to domain APIs and left `products-overview` as compatibility fallback.
- V2.4.2 switched Requirement writes to relation-table CRUD and added server-side pagination, search, filters, sorting, and cursor support for the requirement pool.