feat: 建立可靠通知、吊销与跨实例状态

This commit is contained in:
weijuesen
2026-08-14 01:41:14 +08:00
parent a6a996a518
commit a25bc7abc6
22 changed files with 1017 additions and 245 deletions
+29
View File
@@ -969,3 +969,32 @@ MVP 沿用 IoTDB(现状);TDengine 作为生产规模化候选(先基准
### 回滚点
- 本记录仅修改文档,无代码、数据库、服务器或生成产物变更;如需回滚,删除本记录并恢复相关计划/决策表即可。
## 2026-08-14 整改 Task 8:建立可靠通知、吊销与跨实例状态
### 做了什么
- 新增 `outbox_events``notifications` 表和 `000004_notifications_outbox` 迁移,通知列表从进程内存改为 PostgreSQL 持久化;
- 新增 `Outbox.PublishTx(tx, event)`:业务事务内写入事件,重复 `eventId` 通过唯一索引幂等;worker 领取、发送、退避重试并记录 `pending/sending/sent/retry/failed/cancelled`
- JWT 吊销与登录限流迁移到 Redis:新增 `middleware.StateStore`/`RedisState`,Redis 不可用时登录、刷新、吊销和已认证接口返回 503,不再静默回退单机内存;
- 巡检风险微信推送改为事务内写 Outbox,不再使用进程内 goroutine;微信发送结果保存模板、用户授权、微信 `errcode/errmsg`、尝试次数和最终状态;
- `/notifications` 改读 PostgreSQL;手动通知也落库。
### 设计思路与决策依据
- 可靠通知不能依赖进程内存;PostgreSQL 保存事件与业务同事务,Redis 只保存短时效的吊销和限流状态,降低多实例一致性风险;
- Outbox 幂等由 `event_id` 唯一索引和 `ON CONFLICT DO NOTHING` 保证;worker 领取时用 `pending/retry -> sending` 原子更新,避免多实例重复处理;
- Redis 不可用时采用保守失败而不是降级:认证状态和限流丢失会造成越权或绕过风险,业务价值大于可用性损失;
- 微信未绑定或未授权不是临时失败,写入 `cancelled`;模板未配置或微信返回错误进入重试/最终失败,便于人工查看。
### 验证结果
- `scripts/verify.ps1` exit 0Go test/vet/build、Web test/lint/build、小程序 typecheck/build、APP typecheck/lint、AI pytest 15/15 均通过;
- 新增测试覆盖 Outbox 幂等发布、重启后领取 pending、Redis 状态不可用保守失败、吊销跨状态、登录锁定/清空和微信响应码解析;
- 未部署开发服务器,未执行 `000004` 迁移;未做真实 Redis/微信联调和进程重启演练。
### 回滚点
- 本任务前分支提交为 `a6a996a`;回滚可还原 Task 8 提交;
- 数据库回滚执行 `000004_notifications_outbox.down.sql`,可删除 `notifications``outbox_events`;未发送的 Outbox 数据会随回滚丢失,回滚前必须先备份或暂停 worker;
- 认证状态回滚需恢复旧二进制,Redis 中的吊销/限流键由 TTL 自然过期。