feat(#1714): prepare_direct_upload 去重 + 预建 PROCESSING asset 占位 #1730
Reference in New Issue
Block a user
Delete Branch "feature/prepare-dedup-1714"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
背景
当前 direct 两段式上传的 prepare 只签名 OSS 表单、不做去重(去重只在 complete),导致重复文件每次都完整上传一遍 OSS 才在 complete 阶段被跳过,浪费带宽。
改动
schema(
apps/api/app/schemas/upload.py)DirectUploadPrepareRequest增加client_upload_id(客户端幂等 token)DirectUploadPrepareResponse扩展 3 个向后兼容字段:duplicated: bool=False、skip_transfer: bool=False、asset_id: str=""prepare_direct_upload(
apps/api/app/api/routes/upload.py)file_hash或client_upload_id非空,先调_find_duplicate_asset去重(复用现有 3 级查找:client_upload_id → file_hash → 同名兜底)duplicated=True, skip_transfer=True, asset_id=existing.id,upload_url/fields 为空——前端识别后跳过 OSS 直传,直接走 complete_create_pending_asset预建一条 PROCESSING 占位 asset(写入 file_hash/client_upload_id/storage_key/filename/size),占住 file_hash 闸门,响应带asset_id;预建失败 try/except 降级不阻塞签名_create_pending_asset 改 find-or-create
_find_duplicate_asset 兜底规则细化
测试
12 个新单测(
tests/unit/test_prepare_dedup_1714.py):全量 14400 passed(5 个已知 TTS 沙箱失败与本次无关),diff coverage 85%+。
前端配合
后端 prepare 响应已带
skip_transfer+asset_id,前端识别后跳过 OSS 直传、直接调 complete(前端工程师跟进)。🚀 预览环境已部署
代码审查结果 - PR #1730
⚠️ 问题(2个需要修改)
existing_hash为空(旧占位)而file_hash不为空时,代码进入else分支判定为命中。这会导致不同内容(同名但 hash 不同)的新上传被错误关联到旧的空 hash 占位记录上,造成数据混乱或去重失效。_create_pending_asset中字段补齐失败时异常被静默吞掉(pass)。如果补齐file_hash等 ID 关键字段失败,会导致内存对象与数据库记录不一致。后续流程(如 complete)若依赖 DB 中的这些字段进行校验,将导致业务逻辑错误。💡 建议(1个可选)
logger.warning("预建 asset 占位失败,降级走 old flow: %s", error)仅打印异常对象,建议使用exc_info=True或exc_info=error以便排查预建失败的根本原因。✅ 格式检查通过 | ❌ 逻辑审查需修改 | ✅ 性能良好
🤖 由 AI 代码审查机器人自动生成 | 2026-09-06 04:28:09 | 模型:
🗑️ 预览环境已清理
PR #1730 已关闭或合并,对应的预览环境已被清理。