## Why 自动停复机没有独立队列,在哪个任务里触发就在哪里同步调网关并 sleep 重试;激活、重置、订单后的复机在裸 goroutine 里执行,失败只打日志;退款走人工停机接口,失败后 Outbox 重投与补偿扫描反复补发(生产 2026-10-22:24 小时失败约 26.8 万次);设备下多张卡(生产约 58% 设备跨运营商账户)可能被并发的判断互相覆盖,造成翻转。另外暂停轮询的卡套餐到期、退款后无套餐也应停机,但现有设计会漏停。本 Change 是《轮询按运营商账户限流技术方案》第五部分第 3 节第 6 步。 ## What Changes - 新增停复机指令队列:所有自动入口(套餐步骤、Outbox 三个卡观测消费者、套餐激活、流量重置、订单支付后、退款后资产处理、套餐到期、运营商账户实名管控修改)只"请求评估",由统一判断函数生成指令,进入卡所属运营商账户的停复机队列,优先级最高、先于卡任务领取。 - 同卡只保留一条指令,新覆盖旧并递增版本号;收尾按版本号判断,执行期间生成的新指令不会被删除。 - 执行器:执行前按规则重新判断;只调用一次上游、不 sleep 重试;单卡最小重试间隔(停机与复机合计,按账户配置);结果未知按"确认延迟 → 查状态 → 已是目标状态结束 / 否则按间隔重发"处理,不沿用现有人工核对恢复;失败按错误分类退避、告警,指令不丢弃;终态不重试。 - 设备维度判断队列:按设备合并请求、保存并合并请求场景、版本号再判断、设备锁内只判断不调网关,为设备下各卡生成指令进各自账户队列。 - 到期即停:套餐到期且资产无其他有效套餐时,以"套餐到期"场景直接请求评估(不经过套餐步骤)。 - **BREAKING** 暂停轮询口径:暂停轮询的卡或设备,套餐到期、退款后无可用主套餐照常停机(只触发一次,不做补偿扫描);其他自动停复机仍不做。 - **BREAKING** 退款后资产处理不再调用 `ManualStopCard`:改为请求评估,请求写入成功即视为资产后处理完成,停机失败由指令队列退避与告警处理,不再触发 Outbox 重投与补偿扫描。 - **BREAKING** 激活、重置、订单后的复机去掉裸 goroutine,改为事务提交后请求评估。 - 运营商账户实名管控修改后对受影响的卡批量请求评估(0 → 1 在线未实名,1 → 0 停机未实名),按账户 QPS 平滑执行。 - 全局开关 `polling.stop_resume_queue_enabled`(受控系统配置,默认关闭):开启后所有账户的自动停复机经指令队列,不按账户灰度;关闭即回退为各入口当场执行。 - 停复机方向的失败接入失败告警表;监控增加停复机成功、失败、重试与指令队列长度。 ## Capabilities ### New Capabilities - `stop-resume-command-queue`:请求评估与统一判断、指令覆盖与版本、执行器与单卡最小重试间隔、结果未知确认、失败退避与告警、设备维度判断与场景合并、自动入口统一、全局开关与回退。 ### Modified Capabilities - `card-stop-resume`:"暂停轮询的卡不自动停复机"增加套餐到期与退款后无套餐照常停机;新增"套餐到期即停"。 ## Impact - 依赖:第 1 个(限流、错误分类、停复机记录)、第 4 个(新规则转正)、第 5 个(账户调度、NSQ、失败告警表)Change 已上线。 - 数据库:`tb_system_config` 插入 `polling.stop_resume_queue_enabled` 与结果未知告警阈值;新的成对迁移。 - 代码:`internal/service/iot_card/stop_resume_service.go`(`EvaluateAndAct` 只判断、生成指令;抽出执行部分)、`stop_resume_unified.go`;`internal/infrastructure/cardobservation/event.go`;`internal/service/package/activation_service.go`、`reset_service.go`、`internal/service/order/service.go`;`internal/service/refund/service.go` `stopAsset` 与 `internal/infrastructure/commissiondelivery/event.go` 补偿扫描;`internal/task/package_activation_handler.go`(到期即停);`internal/service/carrier/service.go`;分发器与 NSQ 消费者新增停复机与设备判断;`RedisPollingDeviceOpLockKey` 轮询路径替换。 - 接口:调度参数中的停复机参数生效;`/polling-failure-alerts` 包含停复机方向;`/iot-cards/:id/polling-state` 返回当前指令;监控增加停复机指标。 - 行为:自动停复机比现在晚约 1~2 秒;后台人工点击、通道阈值、自动续费的停复机仍直接执行。