收口审计治理与套餐任务进展
Constraint: 在线热修前必须保存当前迭代分支全部有效代码进展 Confidence: medium Scope-risk: broad Directive: 后续修改需保持审计事件与业务事务边界一致 Tested: git diff --cached --check Not-tested: 未运行全量测试,提交用于切换分支前保存既有工作
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
|
||||
七月迭代分支虽然仍保留旧 `enqueueActivationTask`,但已经具备更合适的本地接续边界:`ActivationService.ActivateNextPendingMainPackage` 负责载体锁、队首选择、条款快照、状态事务和提交后复机;实际激活事务还会原子追加 `card.observation.series.requested` Outbox。套餐状态推进本身是本地数据库用例,不需要再经过一次 Asynq 才能执行。
|
||||
|
||||
本设计仅适用于 `Iteration/7-11`,不包含任何 `main` 分支兼容、纯 Asynq 热修或跨分支移植决策。
|
||||
本设计仅适用于 `Iteration/7-11`,不包含跨分支兼容或移植决策。
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
**Non-Goals:**
|
||||
|
||||
- 不涉及 `main`,不生成可向 `main` cherry-pick 的修复提交。
|
||||
- 不提供跨分支兼容或移植方案。
|
||||
- 不新增套餐激活 Outbox 事件、消费者、迁移或队列类型。
|
||||
- 不删除仍可能被其他旧入口使用的 `TaskTypePackageQueueActivation` 和 Handler;只停止过期接续与孤儿恢复继续走该路径。
|
||||
- 不修改购买、优先级分配、实名激活、流量扣减、退款失效和停复机规则。
|
||||
@@ -106,12 +106,12 @@ Outbox 写入失败时套餐激活事务回滚,避免状态已生效但后续
|
||||
1. 在 `Iteration/7-11` 实施真实孤儿查询和同步接续调用。
|
||||
2. 更新审计覆盖基线与功能总结,执行格式化、静态检查和 `go build ./...`。
|
||||
3. 用只读 SQL/查询计划验证候选公平性,用运行日志和数据库事实核验同步接续及卡观测 Outbox。
|
||||
4. 形成七月分支专属 Lore commit;该提交不面向 `main` 移植。
|
||||
4. 复核七月分支专属差异并保留在当前工作树,不创建提交。
|
||||
5. 发布七月迭代时观察至少两个轮询周期,确认真实孤儿收敛且卡观测 Outbox 正常投递。
|
||||
|
||||
### 回滚
|
||||
|
||||
- 无数据库迁移,回滚七月专属修复提交并重新部署 Worker。
|
||||
- 无数据库迁移,发布后如需回滚,则回退七月专属修复代码并重新部署 Worker。
|
||||
- 已正确激活的套餐保持业务事实,不执行反向 SQL。
|
||||
- 回滚后出现孤儿时,使用带状态条件的单卡修复 SQL逐条处理。
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
## Impact
|
||||
|
||||
- **适用分支**:仅 `Iteration/7-11`;本 Change 不描述、不实施、不引用 `main` 线上热修。
|
||||
- **适用分支**:仅 `Iteration/7-11`,按当前分支的同步接续与卡观测 Outbox 架构独立实施。
|
||||
- **架构通道**:主通道为套餐生命周期复杂写,沿用 `Polling Handler → Package Activation Service → GORM transaction`;辅助通道为 PostgreSQL 候选查询、Redis 载体锁和既有卡观测 Outbox。完整边界只覆盖“旧套餐过期后接续队首套餐及孤儿恢复”,不迁移购买、实名、流量、退款和停复机用例。
|
||||
- **主要代码**:`internal/polling/package_activation_handler.go`、必要时最小调整 `internal/service/package/activation_service.go` 的结果日志;复用现有 `internal/infrastructure/cardobservation/series_event.go` 和公共 Outbox 装配。
|
||||
- **数据库**:不新增表、字段、索引或迁移;只调整现有 `tb_package_usage` 查询和调用顺序。
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
## 0. 七月分支基线与边界
|
||||
|
||||
- [ ] 0.1 在 `Iteration/7-11` 记录套餐激活相关代码、现有卡观测 Outbox 装配和工作树状态,确认本 Change 只覆盖“旧套餐过期后接续队首套餐及孤儿恢复”,不涉及 `main`、线上纯 Asynq 热修或其他套餐用例。验证:相关文件差异摘要不包含跨分支移植计划。
|
||||
- [ ] 0.2 保存生产故障只读基线 `100/100/0`,准备真实孤儿候选 SQL和 `EXPLAIN (ANALYZE, BUFFERS)`;所有 SQL 仅允许读取。验证:SQL 能区分占位记录、真实孤儿和每个载体的稳定队首。
|
||||
- [ ] 0.3 增量更新 `.scratch/tech-global-audit/审计覆盖基线.md`:Audit Event N/A、Domain Ledger N/A、Integration Log N/A,Outbox 明确复用 `card.observation.series.requested` 且不新增事件类型。验证:四类公共能力均有明确决定。
|
||||
- [x] 0.1 在 `Iteration/7-11` 记录套餐激活相关代码、现有卡观测 Outbox 装配和工作树状态,确认本 Change 只覆盖“旧套餐过期后接续队首套餐及孤儿恢复”,不涉及其他套餐用例。验证:相关文件差异摘要不包含跨分支移植计划。
|
||||
- [x] 0.2 保存生产故障只读基线 `100/100/0`,准备真实孤儿候选 SQL和 `EXPLAIN (ANALYZE, BUFFERS)`;所有 SQL 仅允许读取。验证:SQL 能区分占位记录、真实孤儿和每个载体的稳定队首。
|
||||
- [x] 0.3 增量更新 `.scratch/tech-global-audit/审计覆盖基线.md`:Audit Event N/A、Domain Ledger N/A、Integration Log N/A,Outbox 明确复用 `card.observation.series.requested` 且不新增事件类型。验证:四类公共能力均有明确决定。
|
||||
|
||||
## 1. 真实孤儿公平恢复切片
|
||||
|
||||
- [ ] 1.1 修改 `findAndActivateOrphanPackages`:通过 GORM 执行 PostgreSQL CTE/窗口查询,先按卡或设备选择 `priority ASC, created_at ASC, id ASC` 的唯一队首,再用 `NOT EXISTS` 排除 `status IN (1,2)` 的占位载体,最后限制 100 个真实孤儿;删除逐条 `Count` 和 Go map 二次分组。验证:只读 SQL 在前 100 条全部被占位时仍返回窗口后的真实孤儿,同一载体只返回一条队首。
|
||||
- [ ] 1.2 对每个真实孤儿直接调用 `ActivateNextPendingMainPackage`,根据 `activated bool` 和错误记录实际结果,不调用 `enqueueActivationTask`。验证:孤儿路径不存在 `package:queue:activation` 投递,锁冲突和条件未满足不记录成功。
|
||||
- [x] 1.1 修改 `findAndActivateOrphanPackages`:通过 GORM 执行 PostgreSQL CTE/窗口查询,先按卡或设备选择 `priority ASC, created_at ASC, id ASC` 的唯一队首,再用 `NOT EXISTS` 排除 `status IN (1,2)` 的占位载体,最后限制 100 个真实孤儿;删除逐条 `Count` 和 Go map 二次分组。验证:只读 SQL 在前 100 条全部被占位时仍返回窗口后的真实孤儿,同一载体只返回一条队首。
|
||||
- [x] 1.2 对每个真实孤儿直接调用 `ActivateNextPendingMainPackage`,根据 `activated bool` 和错误记录实际结果,不调用 `enqueueActivationTask`。验证:孤儿路径不存在 `package:queue:activation` 投递,锁冲突和条件未满足不记录成功。
|
||||
- [ ] 1.3 执行候选 SQL和 `EXPLAIN (ANALYZE, BUFFERS)`,记录真实孤儿数量、执行耗时和扫描行数;没有性能证据时不新增索引。验证:候选查询无逐载体 N+1,单轮最多返回 100 个载体。
|
||||
|
||||
## 2. 过期接续与 Outbox 一致性切片
|
||||
|
||||
- [ ] 2.1 修改 `processExpiredPackage`:事务内只提交旧主套餐过期和关联加油包失效,事务成功后直接调用 `ActivateNextPendingMainPackage`;删除该路径对 `activateNextPackage/enqueueActivationTask` 的调用。验证:旧状态未提交时不会执行新套餐激活,提交后进程退出可由孤儿扫描恢复。
|
||||
- [ ] 2.2 核对同步接续成功事务继续调用 `appendActivationObservation`,并由现有 Writer 原子追加 `card.observation.series.requested`;不得新增套餐激活 Outbox 事件或消费者。验证:激活状态和卡观测事件同事务成功或回滚,稳定事件 ID仍基于 package usage ID。
|
||||
- [ ] 2.3 收紧轮询日志:仅 `activated=true` 记录本轮成功;锁冲突、无队首、占位变化、等待实名和幂等分别记录明确结果。验证:日志包含载体类型、载体 ID、套餐使用记录或可定位的候选信息和触发来源。
|
||||
- [x] 2.1 修改 `processExpiredPackage`:事务内只提交旧主套餐过期和关联加油包失效,事务成功后直接调用 `ActivateNextPendingMainPackage`;删除该路径对 `activateNextPackage/enqueueActivationTask` 的调用。验证:旧状态未提交时不会执行新套餐激活,提交后进程退出可由孤儿扫描恢复。
|
||||
- [x] 2.2 核对同步接续成功事务继续调用 `appendActivationObservation`,并由现有 Writer 原子追加 `card.observation.series.requested`;不得新增套餐激活 Outbox 事件或消费者。验证:激活状态和卡观测事件同事务成功或回滚,稳定事件 ID仍基于 package usage ID。
|
||||
- [x] 2.3 收紧轮询日志:仅 `activated=true` 记录本轮成功;锁冲突、无队首、占位变化、等待实名和幂等分别记录明确结果。验证:日志包含载体类型、载体 ID、套餐使用记录或可定位的候选信息和触发来源。
|
||||
|
||||
## 3. 七月分支验证与文档
|
||||
|
||||
- [ ] 3.1 对受影响 Go 文件执行 `gofmt`、现有静态检查和 `go build ./...`;按用户要求不新增、修改或运行自动化测试。验证:全量构建退出码为 0,无临时调试标记。
|
||||
- [ ] 3.2 使用只读数据库事实核验:真实孤儿进入候选、同步接续后队首变为 `status=1`、同一载体无第二条生效主套餐、对应卡观测 Outbox 与激活事务一致。验证:保存 SQL、预期和实际结果,不执行批量修复。
|
||||
- [ ] 3.3 新建 `docs/feature-505-package-activation-recovery/功能总结.md` 并更新 README 功能索引,记录七月专属架构、根因、SQL、Outbox 一致性、发布观察、回滚和未执行自动化测试声明。验证:文档不出现 `main`、cherry-pick 或纯 Asynq 热修步骤。
|
||||
- [ ] 3.4 复核七月分支差异并使用中文 Lore commit 提交修复。验证:提交不包含线上 `main` 提案或实现,可独立 revert,`openspec validate fix-package-activation-starvation --strict` 通过。
|
||||
- [x] 3.3 新建 `docs/feature-505-package-activation-recovery/功能总结.md` 并更新 README 功能索引,记录七月专属架构、根因、SQL、Outbox 一致性、发布观察、回滚和未执行自动化测试声明。验证:文档只描述当前分支架构和发布步骤。
|
||||
- [x] 3.4 复核七月分支差异并保留在当前工作树,不创建提交。验证:差异仅包含本 Change,`openspec validate fix-package-activation-starvation --strict` 通过。
|
||||
|
||||
## 4. 七月迭代发布观察
|
||||
|
||||
- [ ] 4.1 部署前记录真实孤儿数量、最老等待时间、同载体重复生效检查和卡观测 Outbox 待投递状态;部署后观察至少两个轮询周期。验证:真实孤儿持续收敛、无重复生效、Outbox 正常投递。
|
||||
- [ ] 4.2 准备回滚说明:无数据库迁移,仅 revert 七月专属修复提交并重新部署 Worker;已正确激活的套餐不反向修改。验证:说明包含观察停止条件和带状态保护的单卡人工恢复边界。
|
||||
- [x] 4.2 准备回滚说明:无数据库迁移,发布后仅回退七月专属修复代码并重新部署 Worker;已正确激活的套餐不反向修改。验证:说明包含观察停止条件和带状态保护的单卡人工恢复边界。
|
||||
|
||||
Reference in New Issue
Block a user