From 3d431f8375e8f2512bba12538bb2ab129a0a0241 Mon Sep 17 00:00:00 2001 From: yeuimu <2197651308@qq.com> Date: Wed, 2 Sep 2026 09:36:17 +0800 Subject: [PATCH] docs(plan): add backup/rollback section, fix backfill run channel and sink semantics --- plans/feature/category-sort-feature.md | 49 +++++++++++++++++++++----- 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/plans/feature/category-sort-feature.md b/plans/feature/category-sort-feature.md index 5548ab2..6d6f629 100644 --- a/plans/feature/category-sort-feature.md +++ b/plans/feature/category-sort-feature.md @@ -24,7 +24,10 @@ - 所有 public 接口入参、出参 DTO 字段**一个都不能变**,只改内部逻辑 - 已有测试必须全部通过,不允许跳过 - 共享开发库(deploy-v2-postgres-1):禁止 reset;迁移用「手写 SQL + db execute + migrate resolve」,先跑 `prisma migrate status` -- 回滚保障:`backups/inkreach_snapshot_20260901_185233.dump`(全库快照已做);代码回滚 = 删 feature 分支 +- 回滚保障(均已就绪,见文末「备份与回滚」): + - DB 全库快照:`backups/inkreach_snapshot_20260901_185233.dump`(pg_dump -Fc) + - 运行容器快照:镜像 `inkreach-api-snapshot:20260901`(docker commit 自 deploy-v2-api-1,含当前代码与依赖) + - 代码回滚 = 删 feature 分支 **执行环境(宿主机无 node,统一用容器跑):** @@ -38,9 +41,11 @@ docker run --rm --network deploy-v2_default \ **排序键定义(getGoods DEFAULT):** ``` -① countries.sort_order(经 goods.country_id) 缺失 → 排最后 -② 叶子.parent_category_id 的 sort_order(二级) 缺失 → 排最后 -③ 叶子自身 sort_order(三级,经 origin_goods.sds_category_id)缺失 → 排最后 +① countries.sort_order(经 goods.country_id) 缺失 → MAX_SAFE_INTEGER +② 叶子.parent_category_id 的 sort_order(二级) 缺失 → MAX_SAFE_INTEGER +③ 叶子自身 sort_order(三级,经 origin_goods.sds_category_id)缺失 → MAX_SAFE_INTEGER +(缺失沉底发生在「所属国家分组内」:如防晒衣(137) 的 sds_category_id=2393 不在新树, + 它会排到日本组末尾,不会破坏国家间顺序,可照常售卖/搜索) ④ good_priority desc, id asc(现有字段,不变) ``` @@ -187,7 +192,7 @@ const norm = (s: string) => s.trim().replace(/\s+/g, ''); const codeOf = (s: string) => (s.trim().match(/^[A-Za-z0-9]+/) ?? [''])[0]; async function main() { - const raw = readFileSync('/opt/inkreach-v2/排序表.md', 'utf8'); + const raw = readFileSync(process.env.SORT_TABLE_PATH ?? '/repo/排序表.md', 'utf8'); let country: string | null = null; let l2: string | null = null; const tree: Array<{ country: string; l2: string; l3: string }> = []; @@ -285,10 +290,13 @@ main().finally(() => prisma.$disconnect()); - [ ] **Step 2.2: 执行脚本** ```bash +# ts-node 不在 apps/api 依赖中,用 tsc 编译后以 node 运行; +# 仓库根只读挂载到 /repo 以读取排序表.md docker run --rm --network deploy-v2_default \ -e DATABASE_URL='postgresql://inkreach:2628adbdf875727ae1b5556b08cb00452bb4e1f80490f6b6@postgres:5432/inkreach' \ - -v /opt/inkreach-v2/apps/api:/app -w /app node:20-alpine \ - npx ts-node prisma/backfill-category-sort-order.ts + -e SORT_TABLE_PATH=/repo/排序表.md \ + -v /opt/inkreach-v2:/repo:ro -v /opt/inkreach-v2/apps/api:/app -w /app node:20-alpine \ + sh -c "npx tsc prisma/backfill-category-sort-order.ts --module commonjs --target es2020 --esModuleInterop --skipLibCheck --outDir /tmp/bf && node /tmp/bf/backfill-category-sort-order.js" ``` Expected: `backfill done`,退出码 0。已知候选 UNMATCHED:美国/内衣 `DG170G170G女士无痕三角内裤`(库内为 `DG701 170G女士无痕三角内裤`,货号前缀 `DG170G170G` 不匹配)→ 将排序表.md 该行改为与库名一致后重跑;其余逐条人工核对。 @@ -693,7 +701,7 @@ Expected: 全部 PASS。任何失败必须修复(含其他模块被 schema 变 - [ ] `prisma migrate status` 干净(无未应用/未登记迁移) - [ ] 回填 UNMATCHED 清单为空(或已逐条人工处理并记录) -- [ ] 冒烟(真实调用形态):`/public/goods?pageSize=10` DEFAULT = 美国 DG001 族 → DG004 族 …;`/public/goods?categoryId=659`(女士服装,跨国)按国家顺序排;`/public/goods?categoryId=666` 同上;`/public/goods?countryId=49&categoryId=658` 只返回英国男装且按 ②③④;`/public/categories` 返回新树且沙特(空)不出现 +- [ ] (先完成 Step 6.4 重建容器)冒烟(真实调用形态):`/public/goods?pageSize=10` DEFAULT = 美国 DG001 族 → DG004 族 …;`/public/goods?categoryId=659`(女士服装,跨国)按国家顺序排;`/public/goods?categoryId=666` 同上;`/public/goods?countryId=49&categoryId=658` 只返回英国男装且按 ②③④;`/public/categories` 返回新树且沙特(空)不出现 - [ ] DTO 字段逐个对比改动前后(PublicGoodDto / PublicCategoryNodeDto / 分页结构)无增删 - [ ] `git status` 干净,全部提交 @@ -725,3 +733,28 @@ cd /opt/inkreach-v2/deploy && docker compose -f docker-compose.v2.yml up -d --bu - 防晒衣(good_id=137) 的 sds_category_id=2393 修复(排序中沉底) - admin 后台分类拖拽排序 UI(本期用脚本回填;后续如需可视化调整再立项) - 中东根更名后 SDS 同步覆盖名称的持久对抗(重跑回填脚本即可恢复) + +--- + +## 备份与回滚(已就绪) + +| 资产 | 位置 | 时间 | +|---|---|---| +| DB 全库快照 | `backups/inkreach_snapshot_20260901_185233.dump`(pg_dump -Fc,3.4M) | 2026-09-01 | +| 运行容器快照 | docker 镜像 `inkreach-api-snapshot:20260901`(711MB,commit 自 deploy-v2-api-1) | 2026-09-01 | +| 代码 | 分支 `feature/category-tree-sort`(develop/refactor-v2 未动) | 实时 | + +**DB 恢复(覆盖式,先停 api 容器避免写入竞争):** + +```bash +cd /opt/inkreach-v2/deploy && docker compose -f docker-compose.v2.yml stop api +docker exec -i deploy-v2-postgres-1 pg_restore -U inkreach -d inkreach --clean --if-exists \ + < /opt/inkreach-v2/backups/inkreach_snapshot_20260901_185233.dump +cd /opt/inkreach-v2/deploy && docker compose -f docker-compose.v2.yml start api +``` + +**api 容器恢复(快照镜像另起实例做比对/应急):** + +```bash +docker run -d --name deploy-v2-api-snapshot --network deploy-v2_default inkreach-api-snapshot:20260901 +```