feat: 停复机指令队列与设备维度判断
Some checks failed
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Has been cancelled
Some checks failed
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Has been cancelled
自动停复机统一经停复机指令队列执行(全局开关 polling.stop_resume.queue_enabled,默认关闭): - 统一判断函数 decideCard,新旧路径共用;暂停轮询的卡在套餐到期、退款场景照常停机 - 同卡一条指令、版本号覆盖;领取校验单卡最小重试间隔;先于卡任务领取,不受 scheduler_mode 限制 - 执行器只调用一次网关,按错误分类退避与告警,结果未知在队列内确认 - 设备维度判断合并请求与场景,版本变化再判断,旧路径持设备锁时推后 - 套餐激活、重置、订单、流量扣减、套餐到期、退款、实名管控修改改为请求评估 - 监控增加停复机队列与近 1 小时执行计数,单卡轮询状态返回当前指令 - 迁移 000255 插入开关与告警、退避参数 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,50 +1,50 @@
|
||||
## 0. 前置确认
|
||||
|
||||
- [ ] 0.1 确认第 1、4、5 个 Change 已上线。
|
||||
- [x] 0.1 确认第 1、4、5 个 Change 已上线。(第 1、4、5 个 Change 已部署测试环境;生产按第五部分第 3 节依赖顺序上线)
|
||||
|
||||
## 1. 迁移与配置
|
||||
|
||||
- [ ] 1.1 新增成对迁移:`tb_system_config` 插入 `polling.stop_resume.queue_enabled`(默认 false)、结果未知告警阈值、停复机退避序列与告警阈值;注册受控系统配置项。
|
||||
- [x] 1.1 新增成对迁移:`tb_system_config` 插入 `polling.stop_resume.queue_enabled`(默认 false)、结果未知告警阈值、停复机退避序列与告警阈值;注册受控系统配置项。(000255;carrierqueue.RegisterConfigDefinitions 注册 queue_enabled、unknown_alert_threshold、backoff_seconds、alert_fail_count,退避序列校验非空递增)
|
||||
|
||||
## 2. 统一判断与请求评估
|
||||
|
||||
- [ ] 2.1 抽出统一判断函数(暂停轮询按场景 → 停机条件 → 复机条件 → 通道阈值锁),`EvaluateAndAct`、`resumeSingleCard`、`resumeDeviceCards`、`ResumeCardIfStopped` 改为调用它。
|
||||
- [ ] 2.2 新增"请求评估(卡或设备、场景、来源)"门面:开关开启时单卡生成指令、设备请求设备判断;关闭时走旧路径当场执行。
|
||||
- [ ] 2.3 指令写入 Lua:覆盖并 `HINCRBY ver`、方向相反清零失败计数、放入卡所属账户 `stop_resume`。
|
||||
- [x] 2.1 抽出统一判断函数(暂停轮询按场景 → 停机条件 → 复机条件 → 通道阈值锁),`EvaluateAndAct`、`resumeSingleCard`、`resumeDeviceCards`、`ResumeCardIfStopped` 改为调用它。(decideCard:EvaluateAndAct 新旧两条路径共用;暂停轮询的卡只在套餐到期、退款场景放行无套餐停机;通道阈值锁在复机写指令与执行前判断)
|
||||
- [x] 2.2 新增"请求评估(卡或设备、场景、来源)"门面:开关开启时单卡生成指令、设备请求设备判断;关闭时走旧路径当场执行。(RequestAssetEvaluation 门面;EvaluateAndAct、ResumeCardIfStopped、CheckAndStopCard 签名不变,开关开启时改为写指令或请求设备判断,场景经 ctx 传入)
|
||||
- [x] 2.3 指令写入 Lua:覆盖并 `HINCRBY ver`、方向相反清零失败计数、放入卡所属账户 `stop_resume`。(srWriteLua:HINCRBY ver、方向相反清零 fail/pending/unknown、ZADD LT;执行中只更新内容与版本)
|
||||
|
||||
## 3. 指令领取与执行
|
||||
|
||||
- [ ] 3.1 分发器在卡任务之前领取 `stop_resume`:清理过期 `sr_running`,领取数 = min(剩余 QPS, `sr_inflight_limit` − 执行中),校验 `sr_last_call` 推后,写 `sr_claim` 并记版本;开关开启后对全部账户领取。
|
||||
- [ ] 3.2 NSQ `polling.stop_resume.{cid}` 专用消费者:核对 token、抢 `sr_exec`、续期。
|
||||
- [ ] 3.3 执行器:按场景重新判断 → 写 `sr_last_call` → 调用一次网关(限流等待模式)→ 成功沿用现有回写与停复机记录;收尾按版本移除或保留。
|
||||
- [ ] 3.4 结果未知:置待确认,确认延迟后先判断再查状态,按规则结束、重发或推后;查询失败不重发;连续未知达阈值告警。
|
||||
- [ ] 3.5 失败分类处理:频率限制、终态(含自动关闭轮询)、已是目标状态、账户配置错误、临时故障与业务错误;停复机方向写入 `tb_polling_failure_alert`;指令不丢弃。
|
||||
- [x] 3.1 分发器在卡任务之前领取 `stop_resume`:清理过期 `sr_running`,领取数 = min(剩余 QPS, `sr_inflight_limit` − 执行中),校验 `sr_last_call` 推后,写 `sr_claim` 并记版本;开关开启后对全部账户领取。(dispatchStopResume 在 dispatchCarrier 前执行,容量 = min(停机/复机所在限流组剩余, sr_inflight_limit, 消费能力);领取 Lua 校验 sr_last_call 推后;只看开关,不受 scheduler_mode 限制)
|
||||
- [x] 3.2 NSQ `polling.stop_resume.{cid}` 专用消费者:核对 token、抢 `sr_exec`、续期。(polling.stop_resume.{cid} 专用 ConsumerManager,核对 token 抢 sr_exec;单次执行 ≤60 秒、租约 2 分钟,不续期)
|
||||
- [x] 3.3 执行器:按场景重新判断 → 写 `sr_last_call` → 调用一次网关(限流等待模式)→ 成功沿用现有回写与停复机记录;收尾按版本移除或保留。(StopResumeExecutor:DecideCommand → MarkStopResumeCall → ExecuteCommand 单次调用(限流等待模式)→ 现有回写与停复机记录;srFinishLua 按版本移除或保留)
|
||||
- [x] 3.4 结果未知:置待确认,确认延迟后先判断再查状态,按规则结束、重发或推后;查询失败不重发;连续未知达阈值告警。(超时、连接失败、MaybeAccepted、成功后回写失败 → pending;确认延迟后先判断再查状态,查询失败不重发;unknown 达阈值告警)
|
||||
- [x] 3.5 失败分类处理:频率限制、终态(含自动关闭轮询)、已是目标状态、账户配置错误、临时故障与业务错误;停复机方向写入 `tb_polling_failure_alert`;指令不丢弃。(频率限制不计失败按 max(最小间隔, 首个退避) 推后;终态结束并告警,停机方向回写已停,自动关闭轮询沿用 TerminalPollingDisabler;已是目标状态按成功回写;account_config 首次告警;其余计失败按停复机退避序列;check_type=stop_resume 写入 tb_polling_failure_alert)
|
||||
|
||||
## 4. 设备维度判断
|
||||
|
||||
- [ ] 4.1 请求设备判断 Lua:`INCR eval_ver`、`SADD eval_scenes`、`ZADD LT device_eval:queue`。
|
||||
- [ ] 4.2 分发与消费:抢 `device_eval:dispatch_lock` 领取,NSQ `polling.device_eval`;消费者抢 `eval_lock`(检查旧路径设备锁),读最新数据判断,为各卡写指令(记录场景)。
|
||||
- [ ] 4.3 收尾:`SREM` 已处理场景,比较版本,变大则 score 设为当前时间再判断。
|
||||
- [ ] 4.4 轮询路径不再使用 `RedisPollingDeviceOpLockKey`;人工设备停复机保持不变。
|
||||
- [x] 4.1 请求设备判断 Lua:`INCR eval_ver`、`SADD eval_scenes`、`ZADD LT device_eval:queue`。(deviceEvalRequestLua:INCR eval_ver、SADD eval_scenes、ZADD LT)
|
||||
- [x] 4.2 分发与消费:抢 `device_eval:dispatch_lock` 领取,NSQ `polling.device_eval`;消费者抢 `eval_lock`(检查旧路径设备锁),读最新数据判断,为各卡写指令(记录场景)。(device_eval 全局分发锁领取,polling.device_eval 消费者抢 eval_lock;旧路径设备锁存在时推后 5 秒;EvaluateDeviceCommands 逐卡统一判断并写指令)
|
||||
- [x] 4.3 收尾:`SREM` 已处理场景,比较版本,变大则 score 设为当前时间再判断。(deviceEvalFinishLua:SREM 已处理场景,版本变大立即再判断)
|
||||
- [x] 4.4 轮询路径不再使用 `RedisPollingDeviceOpLockKey`;人工设备停复机保持不变。(开关开启时轮询路径经设备判断,不再抢 RedisPollingDeviceOpLockKey;人工设备停复机不变)
|
||||
|
||||
## 5. 自动入口改造
|
||||
|
||||
- [ ] 5.1 套餐步骤与 Outbox 三个卡观测消费者改为请求评估,不再同步调网关、不 sleep 重试。
|
||||
- [ ] 5.2 `resumeAfterActivation`(4 处)、`reset_service.go:400`、`order/service.go:2196` 去掉 goroutine,事务提交后请求评估。
|
||||
- [ ] 5.3 `refund/service.go` `stopAsset` 改为请求评估,写入成功即标记 `asset_reset`;`RecoverRefundPostProcessing` 只补偿"请求未写入"。
|
||||
- [ ] 5.4 `package_activation_handler.go` 到期失效处:无其他有效主套餐时以"套餐到期"场景请求评估;接续激活路径不变。
|
||||
- [ ] 5.5 `carrier/service.go` 实名管控修改后按 0 → 1、1 → 0 筛选受影响卡批量请求评估(设备卡按设备)。
|
||||
- [x] 5.1 套餐步骤与 Outbox 三个卡观测消费者改为请求评估,不再同步调网关、不 sleep 重试。(套餐步骤经 EvaluateAndAct;Outbox 网络、实名、流量三个消费者标场景 network_observed / realname_observed / flow_observed)
|
||||
- [x] 5.2 `resumeAfterActivation`(4 处)、`reset_service.go:400`、`order/service.go:2196` 去掉 goroutine,事务提交后请求评估。(stopresume.RunAfterCommit:开关开启时事务提交后同步请求评估、不起 goroutine;关闭时沿用 goroutine 当场执行;流量扣减后停机同样处理)
|
||||
- [x] 5.3 `refund/service.go` `stopAsset` 改为请求评估,写入成功即标记 `asset_reset`;`RecoverRefundPostProcessing` 只补偿"请求未写入"。(开关开启时 stopAsset 以 refund 场景请求评估,写入成功即标记 asset_reset;关闭时沿用 ManualStopCard;补偿扫描只会补"请求未写入"的退款)
|
||||
- [x] 5.4 `package_activation_handler.go` 到期失效处:无其他有效主套餐时以"套餐到期"场景请求评估;接续激活路径不变。(triggerStopAfterExpiry 以 package_expired 场景请求评估,暂停轮询的卡同样停机;接续激活路径不变)
|
||||
- [x] 5.5 `carrier/service.go` 实名管控修改后按 0 → 1、1 → 0 筛选受影响卡批量请求评估(设备卡按设备)。(RequestRealnameControlEvaluation:0→1 在线未实名、1→0 停机未实名,设备卡按设备,分批 500;仅开关开启时执行,保存接口提交后异步触发)
|
||||
|
||||
## 6. 监控与接口
|
||||
|
||||
- [ ] 6.1 `/polling-stats` 按账户增加停复机队列长度、执行中、成功、失败、重试、结果未知数。
|
||||
- [ ] 6.2 `/iot-cards/:id/polling-state` 返回当前指令(动作、原因、场景、版本、失败次数、待确认)。
|
||||
- [ ] 6.3 重新生成接口文档。
|
||||
- [x] 6.1 `/polling-stats` 按账户增加停复机队列长度、执行中、成功、失败、重试、结果未知数。(/polling-stats/carrier-queues 增加停复机队列长度、到期、执行中、待确认,近 1 小时成功、失败、重试、结果未知)
|
||||
- [x] 6.2 `/iot-cards/:id/polling-state` 返回当前指令(动作、原因、场景、版本、失败次数、待确认)。(返回 stop_resume_queue_enabled、stop_resume_command、last_stop_resume_call_at)
|
||||
- [x] 6.3 重新生成接口文档。
|
||||
|
||||
## 7. 编译与规范校验
|
||||
|
||||
- [ ] 7.1 `gofmt -w`;`go build ./cmd/api ./cmd/worker` 通过。
|
||||
- [ ] 7.2 `openspec validate add-stop-resume-command-queue` 与 `openspec doctor --json` 通过。
|
||||
- [x] 7.1 `gofmt -w`;`go build ./cmd/api ./cmd/worker` 通过。
|
||||
- [x] 7.2 `openspec validate add-stop-resume-command-queue` 与 `openspec doctor --json` 通过。(validate 通过;当前 openspec 无 doctor 命令)
|
||||
|
||||
## 8. 测试环境验证(自动化测试为 N/A,按 ENG-TEST-001)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user