✨ feat(task): 新增四象限任务懒触发自动平移链路(读时派生 + Outbox 异步收敛) - 🧩 为 `Task` 模型新增 `urgency_threshold_at` 字段,并补充复合索引 `user_id,is_completed,urgency_threshold_at,priority` 及相关事件 payload - ♻️ 重构 `TaskService.GetUserTasks`:调整为“缓存/DB 读取原始任务 -> 读时派生优先级(`2 -> 1`、`4 -> 3`)-> 通过 `SETNX` 去重后发布平移事件”的处理链路 - 🚚 新增任务平移事件链路: - `service/events/task_urgency_promote.go` - 事件类型:`task.urgency.promote.requested` - 支持 `Publish` + `RegisterHandler` + `ConsumeAndMarkConsumed` 的事务化消费流程 - 🛡️ 为 `TaskDAO` 新增幂等批量更新能力 `PromoteTaskUrgencyByIDs`,采用条件更新策略,仅对“达到阈值且未完成”的任务生效 - 🔌 更新启动接线逻辑:注册任务平移 handler,并将 `eventBus` 注入 `NewTaskService` - 🧹 修复并升级任务缓存层,统一为 `[]model.Task` 原始模型缓存;同时清理误导性注释,并补充详细中文步骤化注释 - 🔗 打通 `QuickNote` 链路中的 `urgency_threshold_at` 透传与校验,覆盖 `state` / `tool` / `nodes` / `prompt` / `agent_quick_note` 全链路 - 💾 写库时补充落库 `task.UrgencyThresholdAt` - 📝 新增功能决策记录 之前画的饼正在一块块填上~这一块饼填上之后,第一批开发的后端部分基本已经搞定了。后面的功能全都是天马行空的拓展功能。
120 lines
5.7 KiB
Markdown
120 lines
5.7 KiB
Markdown
# 功能决策记录(FDR):任务四象限自动平移(懒触发)
|
||
## 1. 基本信息
|
||
- 记录编号:FDR-2026-03-TASK-URGENCY-PROMOTE
|
||
- 功能名称:任务四象限自动平移(不紧急 -> 紧急)
|
||
- 记录日期:2026-03-16
|
||
- 决策状态:已采纳
|
||
- 负责人:项目协作实现(你 + Codex)
|
||
- 关联模块:
|
||
- `backend/service/task.go`
|
||
- `backend/service/events/task_urgency_promote.go`
|
||
- `backend/dao/task.go`
|
||
- `backend/infra/outbox/*`
|
||
- `backend/middleware/cache_deleter.go`
|
||
|
||
## 2. 背景与问题
|
||
- 业务背景:任务在创建时属于某个四象限,随着时间推进,部分“不紧急”任务应自动进入“紧急”象限。
|
||
- 关键约束:
|
||
- 不引入全局定时任务(避免资源常驻扫描)。
|
||
- 已有缓存删除机制依赖 `cache_deleter`(GORM 写库后自动删缓存)。
|
||
- 已有 outbox 总线可承载异步更新。
|
||
- 原始问题:
|
||
- 如果“读时直接改库 + 删缓存”,会引入写放大与重复触发;
|
||
- 如果“只靠 outbox 异步更新”,在消费延迟窗口内二次访问可能读到旧缓存;
|
||
- 需要在一致性与性能之间取平衡,且用户体验不能差。
|
||
|
||
## 3. 决策目标
|
||
- 目标 1:用户访问任务列表时,优先看到“符合当前时间语义”的象限结果。
|
||
- 目标 2:真实数据修正异步执行,避免把写库延迟绑定到读接口。
|
||
- 目标 3:避免重复投递与重复更新,控制总线与数据库压力。
|
||
- 非目标:
|
||
- 本次不做定时批处理平台;
|
||
- 本次不做分布式多级缓存一致性框架;
|
||
- 本次不做任务系统分库分表改造。
|
||
|
||
## 4. 备选方案
|
||
### 方案 A:定时任务全量扫描并更新
|
||
- 描述:后台周期扫描 `tasks`,到线即批量更新优先级。
|
||
- 优点:数据收敛快、语义直观。
|
||
- 缺点:常驻资源开销高;扫描窗口与峰值冲突风险高;运维复杂度增加。
|
||
- 成本:中高(需要调度、监控、限流与容错)。
|
||
|
||
### 方案 B:读时同步改库(请求内直接 UPDATE)
|
||
- 描述:用户读任务列表时,检测到到线任务后立即写库并删缓存。
|
||
- 优点:实现简单,数据立刻落地。
|
||
- 缺点:读接口变“读+写”;高并发时放大锁竞争;延迟直接转嫁给用户请求。
|
||
- 成本:中(实现快,但后续稳定性成本高)。
|
||
|
||
### 方案 C(采纳):读时派生 + SETNX 去重 + outbox 异步落库
|
||
- 描述:
|
||
- 读请求先按 `urgency_threshold_at` 做“派生展示”(仅本次响应生效);
|
||
- 对需要平移的任务做 Redis `SETNX` 去重;
|
||
- 去重成功后发布 outbox 事件,消费者异步条件更新 DB;
|
||
- DB 更新后由 `cache_deleter` 自动删缓存,完成最终收敛。
|
||
- 优点:
|
||
- 用户先看到正确业务语义,不被异步延迟影响体感;
|
||
- 读链路不阻塞写库;
|
||
- 复用现有 outbox 与 cache_deleter,侵入小、可扩展。
|
||
- 缺点:
|
||
- 派生视图与真实落库存在短暂时间差;
|
||
- 需要维护去重键 TTL 与消费可观测性。
|
||
- 成本:中(实现复杂度适中,长期收益更高)。
|
||
|
||
## 5. 最终决策
|
||
- 采纳方案:方案 C(读时派生 + 异步收敛)。
|
||
- 关键理由:
|
||
- 最符合“性能优先 + 最终一致”目标;
|
||
- 与现有 outbox、缓存失效机制天然兼容;
|
||
- 面向后续通用事件总线扩展(更多异步业务)更友好。
|
||
|
||
## 6. 影响范围
|
||
- 涉及模块:
|
||
- `TaskService.GetUserTasks`:新增读时派生与异步触发。
|
||
- `TaskDAO.PromoteTaskUrgencyByIDs`:新增幂等条件更新。
|
||
- `service/events`:新增任务平移事件发布与消费注册。
|
||
- `cmd/start.go`:新增 handler 注册与 service 注入。
|
||
- 数据与存储影响:
|
||
- `tasks` 新增字段:`urgency_threshold_at`。
|
||
- 新增复合索引:`(user_id, is_completed, urgency_threshold_at, priority)`。
|
||
- outbox 新增事件类型:`task.urgency.promote.requested`。
|
||
- 接口影响:
|
||
- 对外 API 协议不变;
|
||
- 行为层面变为“读时先派生展示、随后异步收敛”。
|
||
- 监控与日志影响:
|
||
- 新增任务平移事件发布/消费日志;
|
||
- 可按 `event_type` 维度观测积压与重试。
|
||
|
||
## 7. 风险与应对
|
||
- 风险 1:outbox 消费延迟导致短时间内 DB 仍是旧值。
|
||
- 应对策略:读时派生保证用户看到新语义;最终由异步消费收敛。
|
||
- 风险 2:同一任务被多次重复投递。
|
||
- 应对策略:`SETNX + TTL` 去重;DAO 层条件更新保证幂等。
|
||
- 风险 3:缓存一致性混乱(误删/抖动)。
|
||
- 应对策略:不在读链路主动删缓存;只在真实写库后由 `cache_deleter` 自动失效。
|
||
|
||
## 8. 验证与回滚
|
||
- 验证方式:
|
||
- 用到线前后样例任务验证 `GetUserTasks` 返回象限变化;
|
||
- 验证 outbox 事件是否成功入队、消费并更新 DB;
|
||
- 验证 DB 更新后缓存是否由 `cache_deleter` 自动清理。
|
||
- 成功判定标准:
|
||
- 用户可在到线后第一时间看到“已平移”结果;
|
||
- DB 在异步窗口后收敛为相同状态;
|
||
- 无明显重复投递和异常写放大。
|
||
- 回滚方案:
|
||
- 关闭任务平移事件发布(保留读时派生)可快速止损;
|
||
- 或回退到“只读不平移”行为(临时关闭派生逻辑)。
|
||
|
||
## 9. 里程碑与后续计划
|
||
- 里程碑 1:完成懒触发主链路与事件消费者落地(已完成)。
|
||
- 里程碑 2:完成联调与基本回归(已完成)。
|
||
- 后续优化项:
|
||
- 增加按 `event_type=task.urgency.promote.requested` 的积压监控面板;
|
||
- 根据线上情况调优去重 TTL;
|
||
- 引入批量聚合发布(按用户或时间窗口)进一步降事件量。
|
||
|
||
## 10. 复盘结论(上线后补充)
|
||
- 实际效果:待补充。
|
||
- 与预期偏差:待补充。
|
||
- 是否需要二次决策:待补充。
|