All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 54s
37 lines
2.4 KiB
Markdown
37 lines
2.4 KiB
Markdown
## Why
|
||
|
||
功能 ID:`hotfix-main-package-activation-recovery`
|
||
|
||
线上已第二次出现原主套餐成功过期、队首待生效套餐仍长期停留在 `status=0` 的故障。只读诊断确认当前孤儿扫描固定取出的 100 条记录全部仍有占位套餐,真实孤儿永远无法进入恢复窗口;同时,过期事务提交前投递 Asynq 会让消费者读到旧套餐仍为生效中并把跳过误判为成功。
|
||
|
||
## What Changes
|
||
|
||
- PostgreSQL 在 `LIMIT 100` 前完成每个载体队首选择和 `status IN (1,2)` 占位排除,删除逐条检查的 N+1 查询。
|
||
- 旧主套餐过期和加油包失效事务提交成功后,才查询队首套餐并投递现有 `package:queue:activation` Asynq 任务。
|
||
- Redis 激活锁冲突返回现有套餐激活冲突错误,让 Asynq 按既有策略重试,不再确认假成功。
|
||
- Asynq Handler 仅在实际推进套餐或确认已完成幂等事实时记录成功;占位阻塞、等待实名和锁冲突记录明确原因。
|
||
- 不新增 Outbox、数据库迁移、依赖或新任务类型,保持线上现有纯 Asynq 架构。
|
||
- 按用户明确要求,不新增、修改或运行自动化测试;使用全量构建、只读 SQL、查询计划和日志核验。
|
||
|
||
## Capabilities
|
||
|
||
### New Capabilities
|
||
|
||
无。
|
||
|
||
### Modified Capabilities
|
||
|
||
- `package-queue-activation`:补充纯 Asynq 过期接续的提交后投递、真实孤儿公平扫描、锁冲突重试和准确成功语义。
|
||
|
||
## Impact
|
||
|
||
- **适用范围**:仅当前 `main` 线上代码。
|
||
- **架构通道**:旧套餐轮询复杂写用例,沿用 `Polling Handler → GORM transaction → Asynq → Package Activation Service`;不迁移未触碰的套餐模块。
|
||
- **代码**:`internal/polling/package_activation_handler.go`、`internal/service/package/activation_service.go`。
|
||
- **数据库**:无迁移;仅调整 `tb_package_usage` 查询顺序与过滤。
|
||
- **API/前端**:无改动。
|
||
- **依赖**:继续使用 GORM、PostgreSQL、Redis、Asynq 和 Zap,不新增依赖。
|
||
- **性能**:孤儿扫描由最多 101 次查询收敛为一次候选查询和有限任务投递;使用查询计划确认数据库耗时。
|
||
- **审计与可靠性**:Audit Event、Domain Ledger、Integration Log、Outbox 均为 N/A;`tb_package_usage` 是权威状态,现有 Asynq + 周期孤儿扫描负责最终恢复。
|
||
- **验证**:不写自动化测试;执行 `gofmt`、静态检查、`go build ./...`、只读 SQL及日志核验。
|