From 7736ab785e95e297d04aa1cf3a44de1bdb03856a Mon Sep 17 00:00:00 2001 From: chengma Date: Sat, 15 Aug 2026 17:09:09 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E5=BD=92=E6=A1=A3=E4=BB=BB=E5=8A=A1=20?= =?UTF-8?q?#246?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/task/246-admin档口入库码后台批量回写.md | 85 ++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 docs/task/246-admin档口入库码后台批量回写.md diff --git a/docs/task/246-admin档口入库码后台批量回写.md b/docs/task/246-admin档口入库码后台批量回写.md new file mode 100644 index 0000000..f82768f --- /dev/null +++ b/docs/task/246-admin档口入库码后台批量回写.md @@ -0,0 +1,85 @@ +# 246 Admin:档口入库码后台批量回写与进度反馈 + +- 类型:需求 +- 父级大工单:#14 +- 所属 MVP / 版本:#224 +- 状态:已完成 +- 日期:2026-08-15 +- Gitea 工单:http://ilaer.eicp.net:8418/chengma/cmautobuy/issues/246 + +## 背景与目标 + +原“回写顺运宝”在浏览器请求内同步处理,并把 20 条同时当成选择上限。每条记录可能执行 +写前读取、删除旧值、写入新值和写后核对,数量增加后页面会长时间等待,也难以区分仍在 +执行、请求超时和结果未知。 + +本工单允许采购员一次提交当前页全部选中记录,页面立即返回;Admin 在后台安全串行回写, +页面可以刷新查看批次进度和逐条结果。 + +## 最终方案 + +- 继续只使用 `syb_inner_code_records` 一张业务表,不新增批次表。MySQL schema v25 增加 + `apply_batch_id`、`apply_queued_at`、批次索引,并让状态约束支持 `queued`。 +- 提交时使用单个事务把全部选中且仍为 `ready` 的记录改为 `queued`。任一记录状态已变化, + 整批回滚,避免部分入队和重复回写。 +- HTTP 请求只负责校验顺运宝会话、落库排队和返回页面。Handler 使用单一互斥后台执行器, + 每次最多读取 20 条,但每条仍原子领取为 `applying`,逐条执行既有“写前核验、最多一次 + 写入、写后复读”门禁。 +- 页面按 `apply_batch_id` 从业务表聚合进度,使用文字和原生 `progress` 同时显示总数、排队中、 + 回写中、成功、已存在、跳过、失败、需核对,并用普通 GET 链接手工刷新;模块切换状态会 + 保留当前批次标识。 +- 后台异常时,同批次 `applying` 立即转 `needs_check`,`queued` 恢复 `ready`;Admin 重启时 + 执行相同安全原则。两种情况都不自动重放真实远端写入。 +- 与建单方案一致;实现时进一步补强了“后台进程未退出但执行器异常”的立即状态收敛,避免 + 必须等到下次重启才能看到 `applying` 的未知结果。 + +## 改了哪些 + +- `admin/repository/mysql_db.go`、`admin/repository/mysql_db_integration_test.go`:追加 v25 迁移、 + schema 自检和 v24 升级/重放用例。 +- `admin/model/inner_code.go`、`admin/repository/inner_code.go`:增加排队状态、单表批次字段、 + 原子入队/领取、进度聚合、异常和启动恢复。 +- `admin/service/inner_code_apply.go`、`admin/service/inner_code_match.go`、 + `admin/service/inner_code_page.go`:实现后台分组消费并让排队记录继续占用已匹配明细。 +- `admin/handler/web/inner_code.go`、`admin/handler/web/web.go`:提交后立即重定向,后台批次串行 + 执行并在异常时收敛状态。 +- `admin/templates/inner_code/list.html`、`admin/static/css/app.css`、`admin/static/js/app.js`:增加 + 可访问的进度区、排队中状态、手工刷新和新的提交反馈。 +- `admin/**/*_test.go`:覆盖超过 20 条入队、整批冲突回滚、进度聚合、异常恢复、页面语义和 + 模块状态保留。 +- `docs/admin/03-data-model.md`、`docs/admin/05-ui-specification.md`、 + `docs/admin/08-顺运宝接口.md`:同步稳定数据、页面和远端安全约束。 + +## 验收结果 + +| 验收标准 | 结果 | +|---|---| +| 超过 20 条可一次提交,HTTP 页面不等待远端处理 | 通过:45 条单元测试一次原子入队;Handler 排队后立即 303 | +| 后台每次最多读取 20 条,远端仍逐条且最多写一次 | 通过:分组常量和既有写入未知结果不重试测试通过 | +| 页面显示批次进度并可手工刷新 | 通过:模板语义、原生 `progress`、刷新链接和状态保留测试通过 | +| 重复提交或并发状态变化不会部分入队 | 通过:条件更新、受影响行数校验和事务回滚测试通过 | +| 后台异常和 Admin 重启按远端风险区分恢复 | 通过:`applying → needs_check`、`queued → ready` 自动化测试通过 | +| MySQL v24 → v25、空库和重复迁移 | 部分通过:用例已编写并通过编译;真实 MySQL 8.4 测试环境未启用 | +| 固定 Go 1.23.0 全量检查 | 通过 | +| 不新增批次表、不修改 Client | 通过 | + +## 测试 + +- 执行的命令: + - `$env:GOTOOLCHAIN='go1.23.0'; go vet ./...; go build ./...; go test ./... -count=1` + - `go test ./repository -run 'TestMySQLMigrate_(真实MySQL8|V24升级V25且后台队列状态有效)$' -count=1 -v` + - `git diff --check` +- 结果:固定 Go 1.23.0 的 vet、全量构建和全量测试通过;格式检查通过。MySQL 定向用例因 + 未设置 `CMAUTOBUY_MYSQL_TEST=1` 而按安全门禁跳过。 +- **没验证到的部分**:当前环境没有名称以 `_test` 结尾的独立 MySQL 8.4 测试库,未实际执行 + v24→v25、空库和重复迁移 DDL;未向真实顺运宝发送档口入库码写请求;未在浏览器中人工 + 观察长批次实时进度。禁止使用生产 `autobuy` 数据库或正式货运单代替这些测试。 + +## 遗留问题 + +上线前必须先备份生产数据库,并在独立 MySQL 8.4 `_test` 库执行 v24→v25 和重复迁移; +真实顺运宝写入需要由用户选择测试货运单人工验收。 + +## 相关提交 + +- `f8f22a1` feat: 档口入库码后台批量回写 (#246)