Files
junhong_cmp_fiber/openspec/changes/finalize-unified-stop-resume-rule/tasks.md
邹进 e7f8c4bae9
Some checks are pending
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Waiting to run
docs: 统一停复机规则转正测试环境验证通过
2026-10-25 18:29:56 +09:00

6.9 KiB
Raw Blame History

0. 前置确认

  • 0.1 确认 rebuild-card-traffic-metering-and-stop-resume 已归档并上线生产(总开关可仍为关闭);第 1、3 个 Change 已上线。(按用户 2026-10-24 决定以测试环境为准:rebuild-card-traffic-metering-and-stop-resume 代码与迁移已在测试环境,第 1、3 个 Change 已部署测试环境;生产前置由维护者发布时确认)

第一次发布:演练与口径补齐(总开关仍关闭,行为不变)

1. 迁移

  • 1.1 新增成对迁移:tb_gateway_error_classification 增加 auto_disable_polling boolean not null default false,为"已销户""风险停机"类终态规则置位;down 删列。(000250_add_error_classification_auto_disable_polling,含"仅终态可置位"约束)

2. 规则演练

  • 2.1 新增演练 Query:按批读取卡与资产数据,复用新规则判断函数(不受总开关影响,始终按新规则判断),支持假设的实名管控配置;只读。(纯判断函数 internal/domain/stopresume,读侧 internal/query/stopresumerule 按 1000 张一批读取绑定、设备轮询开关、套餐、通道实名管控与通道阈值锁;评估主流程仍按逐卡读取,与演练按同一套条件实现,未改为调用同一函数)
  • 2.2 GET /stop-resume-rule/dry-run(运营商账户、停机原因筛选,汇总 + 分页明细),仅超级管理员与平台用户;导出场景 stop_resume_rule_dry_run。(另加 POST /stop-resume-rule/dry-run/export 创建导出任务;明细可按 result 筛选,汇总不受影响)
  • 2.3 同步路由与文档生成入口,重新生成接口文档。

3. 风险停机与已销户关闭轮询

  • 3.1 ShouldStopPollingForRisk 去掉独立卡限制,只关闭该卡自身 enable_polling,不级联设备。
  • 3.2 停复机调用失败时按错误分类查 auto_disable_polling:置位则不重试、关闭该卡轮询、回写 gateway_extend、写审计。(gatewaylimit.TerminalPollingDisabler,卡级停复机与设备停复机共用;扩展状态按返回信息推断"已销户/风险停机",推断不出保留原值;新增审计动作 iot_card.terminal_disable_polling)
  • 3.3 错误分类接口增加 auto_disable_polling 字段,非终态类别勾选时拒绝。(更新请求不传该字段时保留原值;类别改为非终态时自动清除)

4. 第一次发布的编译与验证

  • 4.1 gofmt -w;go build ./cmd/api ./cmd/worker 通过;openspec validate finalize-unified-stop-resume-rule 通过。
  • 4.2 测试环境:演练不改任何状态;开启总开关后抽取 not_realname、carrier_stopped、manual、停因为空各若干张,实际评估结果与演练一致。(2026-10-25:三次演练前后全部卡的网络状态、停因、轮询开关、扩展状态一致,无网关调用、无审计;假设 4 个账户开启实名管控时 2 张未实名开机卡判为将停机;测试环境总开关已开启,31 张卡演练均为不动作,抽查 not_realname、carrier_stopped、停因为空 9 张卡 16:40 后各评估 22~24 次均未停复机;manual 停因在设备 10 测试中满足条件后自动复机,与演练规则一致)
  • 4.3 测试环境:绑定设备的卡返回已销户时只关该卡轮询;复机返回风险停机时不重试并关闭轮询;号码封存不关闭轮询。(复机返回"当前用户已销户":卡 11893 只调 1 次即停止重试,关闭轮询、回写已销户、写审计 iot_card.terminal_disable_polling;卡 11892 临时绑定设备 9 后设备复机返回已销户,只关闭 11892 轮询,设备 9 与 8018 轮询不变,验证后解绑恢复;号码封存经规则测试归为终态且不关闭轮询;非终态规则勾选被拒)

5. 开启新规则(运营与维护者,第一次发布上线后)

  • 5.1 为需要实名的运营商账户设置 realname_control_enabled = 1。(按用户 2026-10-25 决定"生产的都不用管",以测试环境为准:测试环境账户 1580、1583、1589 已开启实名管控)
  • 5.2 生产执行演练并导出明细,运营确认"将被复机 / 将被停机"清单;需保持停机的卡先关闭轮询。(同上,测试环境已执行演练并核对,见 4.2)
  • 5.3 维护者在生产开启 JUNHONG_STOP_RESUME_UNIFIED_RULE_ENABLED 并重启全部进程;首日监控复机成功率与终态错误数,确认稳定运行。(同上,测试环境部署配置已开启总开关并稳定运行;生产不处理)

第二次发布:转正(新规则在生产稳定运行后)

6. 删除总开关与旧口径

  • 6.1 stop_resume_unified.go 并入主逻辑:删除 unifiedStopResumeEnabled 与各分支,autoResumableStopReason 恒为真,autoControlSuspended、unifiedRealnameOK 无条件生效。(stop_resume_unified.go 只保留暂停轮询判断与按通道实名管控的 isRealnameOK)
  • 6.2 stop_resume_service.go 删除旧口径:isRealnameOK 行业卡与 realname_policy 分支、isPollingStopReason 限定、ListByDeviceIDAndPollingStopReasons 的调用。(isPollingStopReason 与 ListByDeviceIDAndPollingStopReasons 已删除;资产自动续费复机同步改为不看停因、暂停轮询不复机、设备取全部停机卡)
  • 6.3 删除 pkg/config/config.go、loader.go、defaults/config.yaml 的总开关,.gitea/workflows/deploy.yaml 与 docker-compose.prod.yml 中的 JUNHONG_STOP_RESUME_UNIFIED_RULE_ENABLED。
  • 6.4 通道阈值新周期复机条件去掉开关分支,固定为新规则复机条件。

7. 实名轮询

  • 7.1 polling_realname_handler.go:删除按行业卡跳过;卡所属账户未开实名管控时跳过查询并按正常间隔重入队;账户查询失败按可恢复失败处理。(与提案不同:未开管控账户中,卡未实名且所在资产有等待实名激活的待生效套餐时照常查询,避免后台囤货套餐无法激活;规范已同步补充)

8. 第二次发布的编译与验证

  • 8.1 gofmt -w;go build ./cmd/api ./cmd/worker 通过;全仓检索无 UnifiedRuleEnabled 残留;openspec validate 与 openspec doctor --json 通过。(validate 通过;当前 openspec 无 doctor 命令)
  • 8.2 测试环境:未开管控账户不查实名;开启管控账户的行业卡查实名并按未实名停机;通道阈值新周期解锁后按新规则复机或只解锁;停复机行为与第一次发布开启总开关后一致。(2026-10-25:部署 f49baff 后只有开启实名管控的账户 1580、1583、1589 下 11 张卡查实名,未开管控的 16 张卡未查;临时为账户 1590 开启管控,行业卡 11485 约 50 秒内被查实名并按 not_realname 停机,关闭管控后自动复机并清空停因;通道阈值新周期解锁复机路径无测试数据,按代码核对与新规则复机条件一致;停复机行为与演练一致)