Files
junhong_cmp_fiber/openspec/changes/archive/2026-08-29-fix-package-expiry-stop-race/proposal.md
break 395e5fb47c
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 11m13s
修复套餐接续停机竞态与轮询兜底
2026-08-29 16:27:48 +08:00

28 lines
2.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## Why
生产诊断发现套餐接续期间会并发投递下一套餐激活任务和无套餐停机检查。停机检查可在新套餐生效后才完成并回写停机,造成卡已具备有效套餐、实名和未耗尽流量却仍以 `no_package` 停机;当前已检出 117 张此类卡,且 13 张在新套餐生效后 120 秒内被停机。
## What Changes
- 将主套餐到期后的“接续下一套餐”和“无有效套餐停机”收敛为同一条按载体串行的决策流程,禁止待生效套餐接续期间以旧快照发起停机。
- 只有在确认不存在可生效的后续主套餐,或后续套餐经业务校验确定不能生效后,才执行无套餐停机检查。
- 套餐接续完成后重新依据当前卡与套餐事实判断停复机,确保有效套餐卡不遗留 `no_package` 停机状态。
- 为既有异常卡提供只读筛选条件和受控人工补偿步骤;补偿前必须重新核验套餐、流量、实名和运营商实时状态,不引入自动批量复机。
- 排查并记录轮询调度、入队与消费覆盖情况;当卡状态轮询仍正常但 `polling:package` 队列项缺失时,仅补入缺失的套餐任务,确保套餐轮询仍可作为即时接续失败后的兜底,不将 Redis/Asynq 运行状态误判为业务终态。
## Capabilities
### New Capabilities
- 无。
### Modified Capabilities
- `package-lifecycle`: 主套餐到期、后续套餐接续及无套餐停机必须基于同一载体的最新权益事实,避免接续成功后错误停机。
## Impact
- 受影响代码:`internal/polling/package_activation_handler.go``internal/polling/queue_manager.go``internal/service/package/activation_service.go``internal/service/iot_card/stop_resume_service.go` 及相关轮询任务装配。
- 受影响运行单元:调度 Worker、Asynq 套餐激活任务、套餐轮询任务。
- 不新增 HTTP API、数据库 Schema 或第三方依赖。
- 生产补偿仅由维护者执行受控外部复机Agent 仅提供只读诊断与候选清单。