6cc334a
d1149b6
0fe24f7
origin/main
2026-09-03 16:14 对商品 55066525387(id 为 1124684165671051264) 重跑「取视频」,过程中程序被重启(为加载新的 Wails 绑定)。结果:
55066525387
id
1124684165671051264
运行数据/视频/55066525387/55066525387_1.mp4
videos
products
video_status='pending'
download_status='running'
app.go 的 prepareVideoFetch 在开始下载之前先清空该商品的视频记录:
app.go
prepareVideoFetch
// 登录通过后才清理旧记录,避免一次登录失效把已下载记录抹掉。 if err := a.db.ReplaceVideos(product.ID, nil, time.Now().Format(...)); err != nil {
而 work.Finalize 在全部下载结束后本来就会再做一次完整替换:
work.Finalize
if err := a.db.ReplaceVideos(product.ID, records, now); err != nil {
所以开头那次 ReplaceVideos(..., nil, ...) 是完全多余的——ReplaceVideos 本身就是「按 product_id 全量替换」,末尾那次已经覆盖了清理旧记录的需求。 它唯一的实际效果就是把记录提前抹掉,让中断窗口从「零」扩大到「整个下载过程」。
ReplaceVideos(..., nil, ...)
ReplaceVideos
原注释说明作者考虑过这个风险,但只防住了「登录失效」这一种情况, 没有防住任务停止、程序重启和崩溃。
程序重启后 download_status='running' 仍然挂着,但没有任何任务在跑。 upload_status='running' 同理。这是个不会自愈的假状态:
upload_status='running'
running 表示「此刻有任务正在处理」,进程一退出这个前提就不成立了。
running
pending
删除 app.go 中 prepareVideoFetch 开头对 ReplaceVideos 的调用 (连同其注释),只保留 work.Finalize 里那一次。
在 Finalize 的那次调用处补注释,写明:
Finalize
视频记录只在这里替换一次。不要在下载开始前先清空——ReplaceVideos 本身就是按 product_id 全量替换,提前清空并不能少做什么,只会让 「文件已下载但记录已被删」的窗口覆盖整个下载过程。任务中断、 程序重启或崩溃都会落进这个窗口,导致磁盘上有文件、库里没记录, 界面表现为「目录」不可点。
注意行为差异:删除后,如果一次取视频在下载阶段之前就失败 (搜同款失败、所有同款都没视频),旧的视频记录会保留下来而不是被清空。 这是期望行为——那些文件确实还在磁盘上。 「没找到视频」的语义由 products.video_status 承担,不由删记录来表达。
products.video_status
在 App 启动(startup / 数据库就绪后)调用一个新的 Store.ResetRunningStatuses() (int, error):
App
startup
Store.ResetRunningStatuses() (int, error)
UPDATE products SET download_status = 'pending' WHERE download_status = 'running'; UPDATE products SET upload_status = 'pending' WHERE upload_status = 'running';
done
failed
none
video_status
internal/
go vet ./... go build ./... go test ./internal/... -v go test ./... cd frontend && npx vite build
单元测试需覆盖:
ResetRunningStatuses
真机验证(负责人执行):
download_status
downloaded
internal/store/product.go
git revert
实施 Agent 依据 AGENTS.md「开始实施前检查工单声明的前置工单,真实依赖未满足时保持待实施」拒绝开工,判断正确——是本工单的依赖声明写错了。
原声明「不允许与前置工单并行」,而 #15 / #17 处于待验收,于是形成死锁。
实际的依赖是代码已合入 main,不是已通过人工验收:
三个提交均已推送到 origin/main,本工单在其之上修改,依赖已满足。 且 #15 / #17 的真机验收关注淘宝风控节奏与货憨憨上传链路, 与本工单的「视频记录替换时机」「启动重置 running 状态」互不重叠。
正文「依赖与并行」一节已更正为允许并行并写明原因,重新派发实施。
提交:16e4f0f fix: 视频记录不再提前清空,启动重置残留的 running 状态 (#18) 已推送到 origin/main。
16e4f0f
改动文件(3 个):app.go、internal/store/product.go、product_test.go。
product_test.go
ReplaceVideos(product.ID, nil, ...)
Store.ResetRunningStatuses()
upload_status
验证结果:go vet ./...、go build ./...、go test ./...、 npx vite build 全部通过。
go vet ./...
go build ./...
go test ./...
npx vite build
9 项硬性验收逐条复核全部通过:前置清空已删且 Finalize 保留; ResetRunningStatuses 只动 running,不碰 video_status 和 videos 表; 未新增 migration;internal/ 未 import wails;未改前端与 internal/store/store.go、video.go;未对 cmsp.db 做任何手工订正 (日志中所有 UPDATE 均为源码行或 t.TempDir() 测试库); 未新增依赖;未执行 git 或 Gitea API;未改动 config.yaml、payloads/。
internal/store/store.go
video.go
cmsp.db
t.TempDir()
config.yaml
payloads/
缺陷二已在真实数据上自证:Codex 修改 app.go 后, 负责人正在运行的 wails dev 自动重编译重启,启动时执行了新增的 ResetRunningStatuses,把 55066525387 卡住的 download_status='running' 重置为 pending。这不是手工订正,是修复本身生效。
wails dev
未覆盖测试:「取视频早期失败保留旧记录」与「下载中途取消保留旧记录」 两个行为没有集成测试。现有结构不便注入,而注入需改动 internal/task/ 或 internal/taobao/,超出本工单范围,实施方按要求停手并报告。
internal/task/
internal/taobao/
待负责人真机验证
文档影响:声明需更新业务规则与术语。尚未执行,待验收后统一处理。
工单保持「待验收」。
No dependencies set.
The note is not visible to the blocked user.
基本信息
依赖与并行
#15 的
6cc334a、#17 的d1149b6与0fe24f7均已提交并推送到origin/main,本工单在这些代码之上修改,依赖已满足。
#15 / #17 的真机验收关注的是淘宝风控节奏与货憨憨上传链路,
与本工单修改的「视频记录替换时机」和「启动重置 running 状态」互不重叠;
若验收发现问题,会在对应工单另行处理,不会因此推翻本工单的改动。
子项目影响
原始需求
要解决什么
复现的真实故障
2026-09-03 16:14 对商品
55066525387(id为1124684165671051264)重跑「取视频」,过程中程序被重启(为加载新的 Wails 绑定)。结果:
运行数据/视频/55066525387/55066525387_1.mp4存在,4514202 字节videos表productsvideo_status='pending',download_status='running'缺陷一:先删后写,中断即丢记录
app.go的prepareVideoFetch在开始下载之前先清空该商品的视频记录:而
work.Finalize在全部下载结束后本来就会再做一次完整替换:所以开头那次
ReplaceVideos(..., nil, ...)是完全多余的——ReplaceVideos本身就是「按 product_id 全量替换」,末尾那次已经覆盖了清理旧记录的需求。
它唯一的实际效果就是把记录提前抹掉,让中断窗口从「零」扩大到「整个下载过程」。
原注释说明作者考虑过这个风险,但只防住了「登录失效」这一种情况,
没有防住任务停止、程序重启和崩溃。
缺陷二:running 状态跨重启不会恢复
程序重启后
download_status='running'仍然挂着,但没有任何任务在跑。upload_status='running'同理。这是个不会自愈的假状态:running表示「此刻有任务正在处理」,进程一退出这个前提就不成立了。做什么 / 不做什么
prepareVideoFetch开头那次多余的ReplaceVideos(..., nil, ...)download_status='running'与upload_status='running'重置为pending55066525387的任何状态(负责人明确要求不手动改),修复后由正常流程自行恢复
ReplaceVideos本身的语义已确认方案
缺陷一
删除
app.go中prepareVideoFetch开头对ReplaceVideos的调用(连同其注释),只保留
work.Finalize里那一次。在
Finalize的那次调用处补注释,写明:注意行为差异:删除后,如果一次取视频在下载阶段之前就失败
(搜同款失败、所有同款都没视频),旧的视频记录会保留下来而不是被清空。
这是期望行为——那些文件确实还在磁盘上。
「没找到视频」的语义由
products.video_status承担,不由删记录来表达。缺陷二
在
App启动(startup/ 数据库就绪后)调用一个新的Store.ResetRunningStatuses() (int, error):running,不碰done/failed/pending/nonevideo_status(它的取值里没有running)videos表需求变化记录
设计与原型门禁
文档影响
以及
running状态的生命周期只在进程内有效、启动时会被重置。交付文档影响
任务记录与可选快照
验收标准
prepareVideoFetch中不再存在下载开始前的ReplaceVideos(..., nil, ...)videos表内容与本次下载结果一致(全量替换生效)download_status='running'被重置为pendingupload_status='running'被重置为pendingdone/failed/pending/none状态video_status和videos表internal/未 import wails验证方式
单元测试需覆盖:
ResetRunningStatuses:造running/done/failed/pending各若干条,断言只有
running被改成pending,其余纹丝不动,返回行数正确ResetRunningStatuses不改动video_status,不删videos记录videos记录仍在videos记录仍在videos被本次结果全量替换真机验证(负责人执行):
且
55066525387的download_status不再卡在「下载中」风险和回退
已被手动删除,
videos表会留下指向不存在文件的记录。缓解:上传路径已有「取第一个
downloaded且文件真实存在」的检查,缺文件场景已被兜住;彻底的磁盘对账在 #16 处理。
app.go与internal/store/product.go,git revert即可。启动重置只把
running改为pending,回退代码不会撤销已重置的状态,但那些状态本来就是残留的假状态,保持
pending是正确的。依赖声明更正(2026-09-03)
实施 Agent 依据 AGENTS.md「开始实施前检查工单声明的前置工单,真实依赖未满足时保持待实施」拒绝开工,判断正确——是本工单的依赖声明写错了。
原声明「不允许与前置工单并行」,而 #15 / #17 处于待验收,于是形成死锁。
实际的依赖是代码已合入 main,不是已通过人工验收:
6cc334ad1149b6、0fe24f7三个提交均已推送到
origin/main,本工单在其之上修改,依赖已满足。且 #15 / #17 的真机验收关注淘宝风控节奏与货憨憨上传链路,
与本工单的「视频记录替换时机」「启动重置 running 状态」互不重叠。
正文「依赖与并行」一节已更正为允许并行并写明原因,重新派发实施。
最终实施证据
提交:
16e4f0ffix: 视频记录不再提前清空,启动重置残留的 running 状态 (#18)已推送到
origin/main。改动文件(3 个):
app.go、internal/store/product.go、product_test.go。prepareVideoFetch中下载开始前的ReplaceVideos(product.ID, nil, ...),只保留
work.Finalize里的全量替换,并补注释说明为什么不能提前清空Store.ResetRunningStatuses(),在同一事务内把download_status/upload_status的running重置为pendingapp.go数据库就绪后调用,失败只记 Warn 不中断启动,行数为 0 时不输出日志验证结果:
go vet ./...、go build ./...、go test ./...、npx vite build全部通过。9 项硬性验收逐条复核全部通过:前置清空已删且
Finalize保留;ResetRunningStatuses只动running,不碰video_status和videos表;未新增 migration;
internal/未 import wails;未改前端与internal/store/store.go、video.go;未对cmsp.db做任何手工订正(日志中所有 UPDATE 均为源码行或
t.TempDir()测试库);未新增依赖;未执行 git 或 Gitea API;未改动
config.yaml、payloads/。缺陷二已在真实数据上自证:Codex 修改
app.go后,负责人正在运行的
wails dev自动重编译重启,启动时执行了新增的ResetRunningStatuses,把55066525387卡住的download_status='running'重置为
pending。这不是手工订正,是修复本身生效。未覆盖测试:「取视频早期失败保留旧记录」与「下载中途取消保留旧记录」
两个行为没有集成测试。现有结构不便注入,而注入需改动
internal/task/或internal/taobao/,超出本工单范围,实施方按要求停手并报告。待负责人真机验证
确认该商品原有的视频记录没有消失
文档影响:声明需更新业务规则与术语。尚未执行,待验收后统一处理。
工单保持「待验收」。