Files
cmautobuy/docs/task/246-admin档口入库码后台批量回写.md
T

86 lines
5.2 KiB
Markdown
Raw Normal View History

2026-08-15 17:09:09 +08:00
# 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)