Files
junhong_cmp_fiber/openspec/changes/archive/2026-03-31-fix-stop-resume-lifecycle-engine/proposal.md

45 lines
3.4 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
停复机与套餐生命周期引擎存在多处系统性缺陷:停机时 `stop_reason` 字段写入不一致导致自动复机链路断裂已耗尽Depleted套餐在到期时无法触发下一个排队套餐激活流量重置后停机卡不自动复机设备类型载体完全缺失复机逻辑`ResumeCardIfStopped` 未检查实名状态。这些问题直接影响用户续费后无法正常上网的核心业务场景。
## What Changes
- **停机原因标准化**`stopCards`(套餐超额停机)补写 `stop_reason=traffic_exhausted` + `stopped_at`,与其他停机路径对齐
- **购买套餐后自动复机**`order/service.go` 支付回调激活套餐后,调用复机回调
- **Depleted 套餐到期处理**`findExpiredMainPackages` 扩展为同时查 `status IN (1,2)`,使已耗尽套餐在到期日触发下一个 Pending 套餐激活与复机
- **流量重置后自动复机**`reset_service` 注入复机回调,重置后对满足条件的卡自动复机
- **设备类型复机覆盖**`ResumeCardIfStopped` 扩展签名支持 `carrierType`,设备类型时遍历绑定的已实名卡逐一复机
- **未实名不自动复机**`ResumeCardIfStopped` 内部统一检查 `real_name_status`,未实名卡静默跳过
- **并发保护**`ResumeCardIfStopped` 加 Redis 分布式锁,防止同一张卡并发触发多次 `gateway.StartCard`
- **告警日志**Gateway 成功但 DB 更新失败时记录 ERROR 日志便于人工排查
- **常量化**`HandleProtectConsistencyCheck` 停机原因提取为 `constants.StopReasonProtectPeriod` 常量
## Capabilities
### New Capabilities
- `auto-resume-on-purchase`:购买套餐(支付回调激活)后触发停机卡自动复机的能力
- `auto-resume-on-reset`:流量周期重置(日/月/年)后触发停机卡自动复机的能力
### Modified Capabilities
- `auto-stop-resume`:扩展复机前置条件(未实名不复机)、添加设备类型支持、添加并发保护
- `package-queue-activation`:扩展过期套餐检测逻辑,将 Depleted 套餐纳入到期检测范围
## Impact
**修改文件:**
- `internal/task/polling_handler.go``stopCards` 补写 `stop_reason` + `stopped_at``HandleProtectConsistencyCheck` 使用 `StopReasonProtectPeriod` 常量
- `internal/service/package/activation_service.go`:更新 `ResumeCallback` 接口签名(增加 `carrierType` 参数);两处调用点更新传参
- `internal/service/iot_card/stop_resume_service.go``ResumeCardIfStopped` 扩展支持 `carrierType`;内部加未实名检查;加 Redis 分布式锁;设备类型时遍历复机绑定卡
- `internal/service/order/service.go`:注入 `ResumeCallback``HandlePaymentCallback` 事务后调用复机
- `internal/service/package/reset_service.go`:注入 `ResumeCallback`;三个重置方法结束后异步调用复机
- `internal/polling/package_activation_handler.go``findExpiredMainPackages` 查询改为 `status IN (1,2)`
- `pkg/constants/iot.go`:新增 `StopReasonProtectPeriod` 常量
- `pkg/constants/redis.go`:新增 `RedisCardResumeLockKey(cardID)` Key 生成函数
- `internal/bootstrap/worker_services.go`:为 `orderService``resetService` 注入 `stopResumeService`
**不在本次范围:**
- `enterprise_device/service.go`SuspendCard/ResumeCard 缺失 Gateway 调用(单独立 Issue 跟踪)
- Gateway + DB 双阶段补偿机制(后期迭代)