Files
junhong_cmp_fiber/openspec/changes/fix-polling-stop-logic/proposal.md
huang 868f5a8ef3
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 9m37s
fix: 修复轮询停机连坐、实名逆转防抖及carrier_stopped原因写入缺失三个逻辑缺陷
2026-04-20 11:24:56 +08:00

43 lines
2.7 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
轮询停复机系统存在三个已确认的逻辑缺陷,导致已实名、有套餐的正常卡被错误停机:
1. **连坐问题**:设备下任意一张未实名卡触发 `stopDeviceCards`,会将同设备所有在线卡(包括已实名卡)一并停机,`not_realname` 是单卡属性,不应扩散至设备维度。
2. **无防抖**`polling_realname_handler` 单次检测到实名逆转1→0即立刻触发停机上游运营商接口在数据同步延迟期间可能短暂返回 false导致误停。
3. **carrier 停机无 stop_reason**`polling_cardstatus_handler` 检测到网关侧停机(在线→停机状态变化)时,只更新 `network_status=0`,不写 `stop_reason`,导致卡的 `stop_reason=''``isPollingStopReason` 判断为非轮询原因,卡永久无法被自动复机。
## What Changes
- **修改 `stop_resume_service.go`EvaluateAndAct**:引入 `isDeviceScopeReason()` 判断,`not_realname` 不再触发 `stopDeviceCards`,只停被评估的单卡;`no_package` / `traffic_exhausted` 保持设备维度停机不变。
- **修改 `polling_realname_handler.go`**:实名逆转时不立即停机,改为写入 Redis 计数器;连续 N 次(默认 3 次)检测到逆转后才触发 `EvaluateAndAct`;检测到 true 时重置计数器。
- **新增常量 `StopReasonCarrierStopped`**`pkg/constants/iot.go`):值为 `"carrier_stopped"`,用于标记运营商侧主动停机。
- **修改 `polling_cardstatus_handler.go`**:检测到在线→停机状态变化时,补写 `stop_reason='carrier_stopped'``carrier_stopped` 不进入 `isPollingStopReason`(运营商停机不自动复机,需人工确认)。
- **新增 Redis Key 常量**`pkg/constants/redis.go``RedisPollingRealnameReversalCountKey(cardID)` 用于实名逆转计数。
## Capabilities
### New Capabilities
无新能力,本次为纯缺陷修复。
### Modified Capabilities
- `polling-stop-resume-logic``not_realname` 停机范围从设备维度缩小为单卡维度;新增 `carrier_stopped` 作为合法停机原因(不参与自动复机)。
- `polling-task-handlers`:实名检查 handler 新增逆转防抖逻辑;卡状态检查 handler 新增 carrier 停机原因写入。
## Impact
**受影响代码:**
- `internal/service/iot_card/stop_resume_service.go`
- `internal/task/polling_realname_handler.go`
- `internal/task/polling_cardstatus_handler.go`
- `pkg/constants/iot.go`
- `pkg/constants/redis.go`
**无 DB 变更**(无迁移文件)。
**无 API 变更**(纯内部逻辑调整)。
**现存数据影响:**
- 已处于 `stop_reason=''` 停机状态的卡(如 card_id=2需人工干预设置正确 `stop_reason` 才能自动复机,本次代码修复不回填存量数据。