Files
junhong_cmp_fiber/openspec/changes/add-stop-resume-command-queue/proposal.md
邹进 42e881576d
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 9m33s
feat: 卡网关按运营商账户限流并记录停复机调用
- 新增网关限流:按本系统运营商账户(卡 carrier_id)→ 限流组 → 操作限制每秒请求数,每次 HTTP 尝试计量,默认限流、仅后台人工点击/通道阈值/自动续费/手动刷新豁免;支持只统计与拦截两种模式,默认只统计
- Asynq 遇限流不计失败、固定短延迟重试;轮询任务与停复机业务重试遇限流短延迟重排
- 停机、复机不再使用网关内部重试,只发一次请求
- 网关返回结构化错误;新增上游错误分类规则表与测试接口
- 新增按月分区的停复机记录表:系统自动停复机只写记录,不再写统一审计与集成日志;普通轮询查询不再写集成日志
- 新增限流组、错误分类、停复机记录、按账户调用统计与枚举后台接口
- 迁移 000243~000246;同步 OpenSpec 提案(含后续 6 个 change)与技术方案、工程约束
2026-10-24 15:06:41 +09:00

36 lines
4.6 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
自动停复机没有独立队列,在哪个任务里触发就在哪里同步调网关并 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 秒;后台人工点击、通道阈值、自动续费的停复机仍直接执行。