Files
junhong_cmp_fiber/openspec/changes/add-gateway-readonly-prod-import/tasks.md
邹进 5cf67b98de
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 9m36s
feat: 网关只读资产改为数据表,只读资产只允许查询类调用
- 新增 tb_gateway_readonly_card(卡 ICCID / 设备 IMEI)与开关 JUNHONG_GATEWAY_READONLY_ENABLED,
  替换环境变量名单 JUNHONG_GATEWAY_READONLY_ICCIDS
- 只读资产只放行查卡状态、查实名、查流量、查设备信息、查设备槽位、同步设备状态;
  停机、复机、限速、实名认证链接与设备写操作在网关出口本地拦截;查表失败按拦截;不缓存
- 测试环境部署开启只读模式;新增技术方案与清理顺序文档

Change: add-gateway-readonly-prod-import

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 17:55:52 +09:00

4.0 KiB
Raw Blame History

1. 只读表与存储

  • 1.1 新增成对迁移:建 tb_gateway_readonly_card(id、identifier 唯一、identifier_type(iccid / imei)、source、remark、created_at),注释写明清理顺序文档;down 删表;不写入数据。
  • 1.2 新增 model 与 internal/store/postgres 存储:按卡号(大写)判断是否只读资产;批量写入(ON CONFLICT DO NOTHING)供导入脚本复用。

2. 网关拦截

  • 2.1 internal/gateway/readonly_guard.go 改为函数接缝 func(ctx, cardNo) (bool, error):查询类路径(/flow-card/status、/flow-card/realName、/flow-card/flow、/device/info、/device/slot-info、/device/sync-info)直接放行不查表;其余路径取请求 cardNo(大写)查表,命中或查表失败则本地拦截,返回 upstream 类别的明确失败并记录 gateway.readonly_card.blocked 日志。
  • 2.2 删除 WithReadonlyCards 与内存名单;doRequest / doRequestWithoutPayloadLog 改调新判断(需 ctx)。

3. 配置与部署

  • 3.1 pkg/config:删除 ReadonlyICCIDs 与 gateway.readonly_iccids 绑定,新增 ReadonlyEnabled(gateway.readonly_enabled → JUNHONG_GATEWAY_READONLY_ENABLED)。
  • 3.2 cmd/api/main.go、cmd/worker/main.go:开关开启时注入只读表判断,并在启动日志说明只读模式已开启。
  • 3.3 docker-compose.prod.yml 传递 JUNHONG_GATEWAY_READONLY_ENABLED、删除旧变量;.gitea/workflows/deploy.yaml 改为 JUNHONG_GATEWAY_READONLY_ENABLED=true。

4. 切换(测试环境,先于推送)

  • 4.1 按 ENG-TEST-001 在测试库执行迁移 up/down/up,核对表结构。(10-29 执行 268→269→268→269,版本 269)
  • 4.2 测试库写入现有两张只读卡(89861590172420410612、89861590172420420169)。
  • 4.3 gofmt、go build ./cmd/api ./cmd/worker、openspec validate add-gateway-readonly-prod-import --strict;提交并推送,以 Gitea Actions 运行成功确认部署。
  • 4.4 部署后核对:只读卡的流量、卡状态、实名查询正常,只读设备详情实时状态正常;对只读卡发起一次停机(后台按钮)被拦截、未发出请求、卡状态未变;对非只读测试卡的查询不受影响。

5. 全量导入(临时脚本 cmd/zz_tmp_*,不提交)

  • 5.1 生产只读导出:卡、设备、有效绑定、卡套餐与设备套餐(待生效 / 生效中 / 已用完)、通道编码与重置日。
  • 5.2 通道映射:按 carrier_code 映射到测试库通道,缺失的按生产配置补建;输出映射与未映射清单。
  • 5.3 写只读表:全部卡 ICCID 与设备 IMEI;核对行数与导出一致。
  • 5.4 导入卡与资产标识(ICCID、虚拟号)、设备与绑定,全部挂测试代理 9「测试采购部」,手机号、虚拟号按原值;同卡号已存在则跳过并记录;把测试卡 12244、12245 也挂到代理 9。
  • 5.5 导入套餐使用记录:保留开始与结束时间、真实已用量、真总量、虚总量、展示倍率、是否启用虚流量、重置周期与下次重置时间、优先级、主套餐 / 加油包关系;订单号 PROD-<原订单号>、订单 ID 占位、package_id 指向测试占位套餐。
  • 5.6 全部导入卡置"待建起点";触发轮询重新加载并确认导入卡进入调度。
  • 5.7 导入后核对:卡、设备、绑定、套餐行数与导出一致;抽查 10 张卡的套餐时间与已用量与生产一致;导入后 1 小时内停复机记录全部为拦截失败、无发出的写请求。

6. 差距报表

  • 6.1 记录导入时刻生产各套餐真实已用量作为起点。
  • 6.2 运行至少 24 小时后,按套餐(设备套餐按设备合并)输出:测试环境新增扣减、生产同期新增扣减、差额、是否已到停机线;汇总卡住卡数、总差额(GB)、按新逻辑已到停机线但生产未停的套餐数。
  • 6.3 用 flowcollector 本月读数给出导入前差距上限,与报表一并提交。