Files
junhong_cmp_fiber/openspec/changes/add-gateway-readonly-prod-import/tasks.md
邹进 0b6b664a7a
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 1m42s
docs: 生产全量数据导入测试环境进度(导出、只读表、导入、轮询加载)
Change: add-gateway-readonly-prod-import

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

39 lines
5.2 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.
## 1. 只读表与存储
- [x] 1.1 新增成对迁移:建 `tb_gateway_readonly_card`(`id`、`identifier` 唯一、`identifier_type`(iccid / imei)、`source`、`remark`、`created_at`),注释写明清理顺序文档;down 删表;不写入数据。
- [x] 1.2 新增 model 与 `internal/store/postgres` 存储:按卡号(大写)判断是否只读资产;批量写入(`ON CONFLICT DO NOTHING`)供导入脚本复用。
## 2. 网关拦截
- [x] 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` 日志。
- [x] 2.2 删除 `WithReadonlyCards` 与内存名单;`doRequest` / `doRequestWithoutPayloadLog` 改调新判断(需 ctx)。
## 3. 配置与部署
- [x] 3.1 `pkg/config`:删除 `ReadonlyICCIDs` 与 `gateway.readonly_iccids` 绑定,新增 `ReadonlyEnabled`(`gateway.readonly_enabled` → `JUNHONG_GATEWAY_READONLY_ENABLED`)。
- [x] 3.2 `cmd/api/main.go`、`cmd/worker/main.go`:开关开启时注入只读表判断,并在启动日志说明只读模式已开启。
- [x] 3.3 `docker-compose.prod.yml` 传递 `JUNHONG_GATEWAY_READONLY_ENABLED`、删除旧变量;`.gitea/workflows/deploy.yaml` 改为 `JUNHONG_GATEWAY_READONLY_ENABLED=true`。
## 4. 切换(测试环境,先于推送)
- [x] 4.1 按 ENG-TEST-001 在测试库执行迁移 up/down/up,核对表结构。(10-29 执行 268→269→268→269,版本 269)
- [x] 4.2 测试库写入现有两张只读卡(`89861590172420410612`、`89861590172420420169`)。
- [x] 4.3 `gofmt`、`go build ./cmd/api ./cmd/worker`、`openspec validate add-gateway-readonly-prod-import --strict`;提交并推送,以 Gitea Actions 运行成功确认部署。(提交 5cf67b98,Gitea Actions 运行 1313 于 17:05:33 成功)
- [x] 4.4 部署后核对:只读卡的流量、卡状态、实名查询正常,只读设备详情实时状态正常;对只读卡发起一次停机(后台按钮)被拦截、未发出请求、卡状态未变;对非只读测试卡的查询不受影响。(10-29 17:06:只读假卡 89860000000000009999 后台停机返回"测试环境只读资产,已拦截调用:/flow-card/cardStop"、卡状态未变;两张只读卡查询正常、无停复机记录;假卡已删除)
## 5. 全量导入(临时脚本 `cmd/zz_tmp_*`,不提交)
- [x] 5.1 生产只读导出:卡、设备、有效绑定、卡套餐与设备套餐(待生效 / 生效中 / 已用完)、通道编码与重置日。(10-29 经 dbhub 分片导出:卡 98,567、设备 20,144、绑定 38,667、套餐 28,681、通道 36)
- [x] 5.2 通道映射:按 `carrier_code` 映射到测试库通道,缺失的按生产配置补建;输出映射与未映射清单。(SBK01 重置日按生产改为 27;新建 28 个通道;36 个全部映射)
- [x] 5.3 写只读表:全部卡 ICCID 与设备 IMEI;核对行数与导出一致。(ICCID 98,567、IMEI 20,139 去重后全部写入,缺失 0)
- [x] 5.4 导入卡与资产标识(ICCID、虚拟号)、设备与绑定,全部挂测试代理 9「测试采购部」,手机号、虚拟号按原值;同卡号已存在则跳过并记录;把测试卡 12244、12245 也挂到代理 9。(新卡 98,558、设备 20,143、绑定 38,664;已存在的 9 张卡与 1 台设备、3 条绑定跳过;12244、12245 挂代理 9)
- [x] 5.5 导入套餐使用记录:保留开始与结束时间、真实已用量、真总量、虚总量、展示倍率、是否启用虚流量、重置周期与下次重置时间、优先级、主套餐 / 加油包关系;订单号 `PROD-<原订单号>`、订单 ID 占位、`package_id` 指向测试占位套餐。(导入 28,676;4,242 条生产计时快照为空,按同名套餐口径补 from_purchase + by_day 30/365 天;订单号前缀 P-;122 个加油包关联主套餐)
- [x] 5.6 全部导入卡置"待建起点";触发轮询重新加载并确认导入卡进入调度。(重新保存轮询配置 29 触发加载;配置 29 只匹配通道 1587 已激活普通卡,导入卡中 3,943 张进入调度,19:05 已有 213 张完成流量检查)
- [ ] 5.7 导入后核对:卡、设备、绑定、套餐行数与导出一致;抽查 10 张卡的套餐时间与已用量与生产一致;导入后 1 小时内停复机记录全部为拦截失败、无发出的写请求。
## 6. 差距报表
- [x] 6.1 记录导入时刻生产各套餐真实已用量作为起点。(起点 = 导出时生产套餐真实已用量,已随套餐导入测试库 data_usage_mb;原始导出与导入脚本留存在 ~/prod-import-20261029/,测试库按 order_id − 800000000 对应生产套餐 ID)
- [ ] 6.2 运行至少 24 小时后,按套餐(设备套餐按设备合并)输出:测试环境新增扣减、生产同期新增扣减、差额、是否已到停机线;汇总卡住卡数、总差额(GB)、按新逻辑已到停机线但生产未停的套餐数。
- [ ] 6.3 用 flowcollector 本月读数给出导入前差距上限,与报表一并提交。