Files
junhong_cmp_fiber/openspec/changes/add-polling-card-status-with-verbose-log/design.md
huang 4a1e44f9e1
Some checks failed
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Has been cancelled
提案
2026-04-15 11:17:23 +08:00

4.0 KiB
Raw Blame History

Context

轮询系统采用分片 Redis Sorted Set + Asynq 任务队列的架构,支持 4 种轮询类型realname / carddata / package / protect。每种类型对应一个 Asynq handler所有 handler 通过 PollingBase 共享并发控制、缓存和重入队逻辑。

Gateway 已提供 QueryCardStatus 接口(返回 CardStatus: "准备" | "正常" | "停机"IotCard model 已有 NetworkStatus int0=停机1=开机),但轮询系统从未主动调用该接口同步状态。

Goals / Non-Goals

Goals:

  • 新增第 5 种轮询类型 polling:card_status,与现有 4 种类型完全对等集成
  • PollingBase 新增 verboseLog bool 字段,所有 handler 在成功查询到上游数据后可选输出详细日志
  • 保持向后兼容:现有轮询配置不受影响,card_status_check_interval 为 NULL 时该类型不参与轮询

Non-Goals:

  • 不修改停复机决策逻辑(EvaluateAndAct 已处理)
  • 不新增 HTTP API纯后台轮询任务
  • 不对现有 4 种 handler 做任何功能性改动,只追加 verbose log 调用

Decisions

决策 1Gateway 状态映射规则

  • "准备"NetworkStatusOnline (1):卡已就绪,视为开机
  • "正常"NetworkStatusOnline (1):正常使用
  • "停机"NetworkStatusOffline (0):停机
  • 理由:与现有 realname handler 的布尔映射风格一致,映射逻辑内联在 handler 内,不引入额外函数

决策 2状态变更后触发 EvaluateAndAct

  • 上游报告状态变化时,先更新 DB + 缓存,再调用 stopResumeSvc.EvaluateAndAct(freshCard)
  • 理由:与 realname/carddata handler 行为完全一致,停复机决策集中在 EvaluateAndAct
  • 替代方案:仅写 DB 不触发评估 —— 拒绝,因为状态变化后不及时评估可能导致卡停复机延迟

决策 3verboseLog 通过配置文件控制

  • pkg/config/config.go 新增 PollingConfig.VerboseLog boolNewPollingBase 接受该参数
  • verboseLog 开启时,每次成功从 Gateway 获取数据后以 Info 级别输出日志
  • 理由:配置文件方式符合项目 Viper 规范,比 Redis key 实现简单,重启代价可接受(轮询系统重启本身就有初始化流程)
  • 替代方案Redis key 动态开关 —— 额外的 Redis 查询开销,且 key 管理增加运维复杂度

决策 4allTaskTypes 驱动初始化和出队

  • queue_manager.go 中的 allTaskTypes slice 控制:初始化时写入哪些队列、RemoveFromAllQueues 清理哪些队列、Scheduler 出队哪些类型
  • 新类型追加到该 slice 即可自动接入所有相关流程,无需修改调度器核心逻辑

决策 5数据库迁移

  • tb_polling_config 新增 card_status_check_interval INT NULLNULL 表示不启用
  • tb_iot_card 新增 last_card_status_check_at TIMESTAMPTZ NULL,与其他 last_*_check_at 字段保持一致
  • 两列均 DEFAULT NULL,完全向后兼容,无需数据迁移

Risks / Trade-offs

  • [风险] card_status 轮询调用量增加约 25%(原 4 种 → 5 种) → 缓解:card_status_check_interval 可配置,初期设置较长间隔(如 300 秒),观察 Gateway 负载后调整
  • [风险] verbose_log 开启后日志量大幅增加 → 缓解:默认关闭(false),生产环境仅在排查问题时临时开启;日志文件已配置 Lumberjack 轮转
  • [权衡] 状态以上游为准 → 若上游短暂故障返回异常状态(如误报"停机"handler 查询失败时会 warn 并重新入队,不更新状态;只有成功响应才触发写 DB

Migration Plan

  1. 执行数据库迁移(make migrate-up
  2. 更新 Worker 二进制并重启(无需 API 服务重启)
  3. 在轮询配置后台为需要卡状态轮询的配置项设置 card_status_check_interval
  4. 初始化器将在 Worker 启动时自动将全量卡写入新的 polling:card_status 队列
  5. 如需回滚:将 card_status_check_interval 设置为 NULL 即可停止该类型轮询,无需重启

Open Questions

无。