fix(#1714): 素材上传去重防重 + complete幂等传递 + 轮询收敛(前端P0) #1716

Closed
opened 2026-09-05 16:02:07 +08:00 by xiaoxia · 1 comment
Owner

背景

Issue #1714:同一文件被反复走完整上传链路(prepare→OSS直传→complete),13 个素材建了 69 条记录、转码队列堆 39 个任务。根因诊断见项目文件 asset_duplicate_upload_rootcause_20260905.md

本 PR 为前端 P0 部分(后端 complete 幂等兜底 + worker 转码孤儿修复由后端 PR 处理)。

改动

1. 入队按文件指纹去重(核心)

  • 新增 src/api/assets/uploadDedup.ts 纯函数模块:
    • makeFileFingerprint:文件名+大小+lastModified 稳定指纹
    • findDuplicateInQueue:队列查重(error 态可重新激活、在途/已完成均拦截)
    • makeClientUploadId:上传幂等 token(一次逻辑上传一个,重试复用)
    • computeFileHash:SHA-256 内容哈希(≤256MB 全量;大文件抽样头尾各 8MB + 文件大小,避免 2GB 上传前卡死;不支持 crypto.subtle 时降级为空串,FileReader 回退)
  • useAssetUpload.enqueueUploads:同一文件已在 preparing/uploading/ingesting/done 时跳过并轻提示;此前 error 的同指纹项重新激活复用 clientUploadId

2. complete 携带 file_hash + 幂等 token

  • prepareDirectUpload / completeDirectUpload 请求体新增 file_hashclient_upload_id(后端 schema 已支持 file_hash,额外字段 Pydantic 忽略不报错,待后端幂等 PR 消费 token)
  • uploadAssetDirect(配音/封面/克隆等非队列链路)自动补算 hash 与 token,去重闸门对所有上传链路生效

3. 超时放宽 + complete 失败不盲目重传

  • prepare 请求超时 10s→30s,complete 10s→60s(complete 内含 OSS 检查+建库+派单)
  • complete 阶段失败(超时/网络/5xx):不重新 prepare、不重新直传,handle 留存,点重试只幂等重发 complete(文件已在 OSS,重发由 file_hash + token 保证不重复建记录);同时立即刷新素材列表,让可能已建成的「处理中」素材可见,消除用户反复重传的动因
  • prepare/transfer 失败(后端尚无记录)才全量重跑

4. 入口防重复提交

  • 直传进行中(transferActive)禁用「上传素材」按钮、拦截文件选择/拖拽并提示;重试按钮仅 error 状态可点,tooltip 区分「安全重试(只确认,不重新上传)」

5. 轮询收敛

  • 素材列表 3s 快轮询加 10 分钟上限:处理中素材创建超 10 分钟仍未就绪时停止快轮询(避免后端孤儿任务导致无限转圈),对应卡片停止转圈并显示「处理超时,可重试上传」橙色遮罩 + StatusPill 文案

测试

  • 新增 src/test/api/uploadDedup.test.ts(9 个):指纹一致性/区分度、队列查重各状态、幂等 token 唯一性、hash 内容区分与 64 位 hex 格式
  • useAssetUpload.test.tsx 新增 2 个集成测试:同文件多次选择不重复入队(1 项/1 次 prepare,完成后重复选择仍不新增,不同文件正常入队)、complete 超时后重试只重发 complete(prepare 1 次、transfer 1 次、complete 2 次)
  • 本地 tsc / eslint / prettier / build 全绿;全量 vitest 623 通过

前端职责边界

  • 未改 .gitea/workflows/ 与 Dockerfile
  • 后端 P0(complete 按 token/file_hash 幂等兜底)与 P1(worker HEVC 转码 key 不一致致孤儿 PROCESSING)由后端 PR 处理;本前端改动向后兼容(额外字段旧后端忽略)
## 背景 Issue #1714:同一文件被反复走完整上传链路(prepare→OSS直传→complete),13 个素材建了 69 条记录、转码队列堆 39 个任务。根因诊断见项目文件 `asset_duplicate_upload_rootcause_20260905.md`。 本 PR 为**前端 P0 部分**(后端 complete 幂等兜底 + worker 转码孤儿修复由后端 PR 处理)。 ## 改动 ### 1. 入队按文件指纹去重(核心) - 新增 `src/api/assets/uploadDedup.ts` 纯函数模块: - `makeFileFingerprint`:文件名+大小+lastModified 稳定指纹 - `findDuplicateInQueue`:队列查重(error 态可重新激活、在途/已完成均拦截) - `makeClientUploadId`:上传幂等 token(一次逻辑上传一个,重试复用) - `computeFileHash`:SHA-256 内容哈希(≤256MB 全量;大文件抽样头尾各 8MB + 文件大小,避免 2GB 上传前卡死;不支持 crypto.subtle 时降级为空串,FileReader 回退) - `useAssetUpload.enqueueUploads`:同一文件已在 preparing/uploading/ingesting/done 时跳过并轻提示;此前 error 的同指纹项重新激活复用 `clientUploadId` ### 2. complete 携带 file_hash + 幂等 token - `prepareDirectUpload` / `completeDirectUpload` 请求体新增 `file_hash`、`client_upload_id`(后端 schema 已支持 `file_hash`,额外字段 Pydantic 忽略不报错,待后端幂等 PR 消费 token) - `uploadAssetDirect`(配音/封面/克隆等非队列链路)自动补算 hash 与 token,去重闸门对所有上传链路生效 ### 3. 超时放宽 + complete 失败不盲目重传 - prepare 请求超时 10s→30s,complete 10s→60s(complete 内含 OSS 检查+建库+派单) - complete 阶段失败(超时/网络/5xx):**不重新 prepare、不重新直传**,handle 留存,点重试只幂等重发 complete(文件已在 OSS,重发由 file_hash + token 保证不重复建记录);同时立即刷新素材列表,让可能已建成的「处理中」素材可见,消除用户反复重传的动因 - prepare/transfer 失败(后端尚无记录)才全量重跑 ### 4. 入口防重复提交 - 直传进行中(`transferActive`)禁用「上传素材」按钮、拦截文件选择/拖拽并提示;重试按钮仅 error 状态可点,tooltip 区分「安全重试(只确认,不重新上传)」 ### 5. 轮询收敛 - 素材列表 3s 快轮询加 10 分钟上限:处理中素材创建超 10 分钟仍未就绪时停止快轮询(避免后端孤儿任务导致无限转圈),对应卡片停止转圈并显示「处理超时,可重试上传」橙色遮罩 + StatusPill 文案 ## 测试 - 新增 `src/test/api/uploadDedup.test.ts`(9 个):指纹一致性/区分度、队列查重各状态、幂等 token 唯一性、hash 内容区分与 64 位 hex 格式 - `useAssetUpload.test.tsx` 新增 2 个集成测试:**同文件多次选择不重复入队**(1 项/1 次 prepare,完成后重复选择仍不新增,不同文件正常入队)、**complete 超时后重试只重发 complete**(prepare 1 次、transfer 1 次、complete 2 次) - 本地 tsc / eslint / prettier / build 全绿;全量 vitest 623 通过 ## 前端职责边界 - 未改 `.gitea/workflows/` 与 Dockerfile - 后端 P0(complete 按 token/file_hash 幂等兜底)与 P1(worker HEVC 转码 key 不一致致孤儿 PROCESSING)由后端 PR 处理;本前端改动向后兼容(额外字段旧后端忽略)
Author
Owner

误建为 issue,实际 PR 已改为 #1717,关闭此条。

误建为 issue,实际 PR 已改为 #1717,关闭此条。
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: xiaoxia/xiaoxia-saas#1716