Files
邹进 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

2.6 KiB
Raw Permalink Blame History

Context

依据 docs/engineering/轮询按运营商账户限流技术方案.md 第三部分第 12、13 节与 14.5 节。

现状:单资产接口 PATCH /assets/:identifier/polling-status(internal/routes/asset.go:140);iot_card.Service.BatchUpdatePollingStatus 仅设备级联内部使用(asset_polling_service.go:96);风险停机或已销户自动关闭(internal/application/cardobservation/network.go:69);支付成功自动恢复已有部分逻辑。导入任务可参照 internal/routes/phone_asset_association.go 的 /unbind-imports。生产 2026-10-24:8,420 张风险停机或已销户卡,均关闭轮询。

Goals / Non-Goals

Goals: 人工批量开关轮询;清单可查、可导出、有历史;停机被拒集中处理;套餐生效类入口自动恢复与老系统一致。

Non-Goals: 导卡时直接设为不轮询(导卡后用文件导入关闭);调度读取清单表;激活状态计算口径。

Decisions

  1. 清单只做记录,调度只认 enable_polling:避免为列表扫描卡大表,也避免两处状态不一致;所有写 enable_polling 的入口统一经一个"改轮询开关"函数,同事务写清单与审计。
  2. 部分唯一索引:(asset_type, asset_id) WHERE status = 已关闭,保证同一资产只有一条已关闭记录;恢复时更新该记录。
  3. 批量逐项事务:每项独立事务,部分失败不影响其他项;返回逐项结果。参照 batch-update-realname-policy 的请求与返回格式。
  4. 导入任务:沿用手机号资产解绑导入的上传与任务模型(文件 key 前缀、CSV、逐行结果)。
  5. 自动恢复轮询的位置:订单 activatePackage(覆盖支付、后台下单、批量下单、OpenAPI 钱包下单)与改有效期接口;恢复后调用"请求评估"(第 6 个 Change 上线前为现有复机路径)。
  6. 存量补写:迁移中按 enable_polling = false 一次性插入,来源按 gateway_extend 区分。
  7. 停机被拒视图:基于 tb_polling_failure_alert 的筛选视图,不新建表。

Risks / Trade-offs

  • [批量关闭误操作] → 确认框展示影响说明;清单保留操作人与原因,可在清单页批量恢复。
  • [存量补写数据量] → 约 8,500 行,一次性迁移可接受。
  • [自动恢复与人工关闭意图冲突] → 已定对齐老系统:客户购买或改有效期即恢复;需要长期停用的卡运营须另行处理。

Migration Plan

  1. 迁移建表并补写存量。2. 测试环境按 tasks 第 8 节核对。3. 维护者发布生产。4. 回退:代码回退;清单表保留。