fix(canvas): keep uploaded resources in asset library (#388)

This commit is contained in:
MasterChiefCN
2026-09-02 20:18:49 +08:00
committed by GitHub
parent 58defbc3b9
commit 16913ee72c
22 changed files with 1154 additions and 34 deletions

View File

@@ -15,7 +15,7 @@ description: 影策后端核心持久化表与状态边界
容器内命令 `migrate-schema up` 应用缺失迁移,`migrate-schema status` 输出当前和期望版本,`migrate-schema verify` 只检查兼容性。`CANVAS_AUTO_MIGRATE=true` 仅用于开发和旧部署兼容;受管生产部署设置为 `false`,并由 Compose 的一次性 `migrate` 服务先完成迁移。后续迁移必须新增版本,不得修改已经发布迁移的实现或校验和。
当前结构版本为 4。版本 2 为 `schema_migrations.applied_at` 增加 `idx_schema_migrations_applied_at` 索引;版本 3 `asset_taxonomy_candidate_identity` 为资产候选增加规范化名称和来源,收敛资产分类,并为待确认候选建立项目内部分唯一索引;版本 4 `resource_upload_key` 为资源上传幂等补充 `resources.upload_key` 列和用户维度唯一索引。
当前结构版本为 5。版本 2 为 `schema_migrations.applied_at` 增加 `idx_schema_migrations_applied_at` 索引;版本 3 `asset_taxonomy_candidate_identity` 为资产候选增加规范化名称和来源,收敛资产分类,并为待确认候选建立项目内部分唯一索引;版本 4 `resource_upload_key` 为资源上传幂等补充 `resources.upload_key` 列和用户维度唯一索引;版本 5 `payment_topup` 创建积分充值、支付通知和对账所需结构。
版本 3 会将 `wardrobe`、`weapon`、`accessory` 迁移为 `prop`,将 `style` 迁移为 `material`,并把原先归入 `other` 的图片、视频、音频和 3D 模型迁移为 `material`。迁移只合并重复的待确认候选:保留最早记录,其余标记为 `ignored`;已经确认的资产不会被自动删除或归并。
@@ -148,4 +148,8 @@ description: 影策后端核心持久化表与状态边界
`resources.upload_key` 保存客户端 `X-Idempotency-Key` 的 SHA-256 摘要。相同用户重复提交同一逻辑上传时复用已有资源;失败重试继续使用原对象路径,避免对象存储已经接收请求但响应丢失时产生第二份物理对象。未提供幂等标识的后台生成资源保持 `NULL`,不参与该唯一约束。
个人画布中的图片、视频和音频采用 `Asset -> Resource` 所有权约束:前端先提交素材,再提交带 `assetId` 的画布节点或时间线直连媒体;后端保存画布前校验资源属于当前用户、状态为 `ready`、素材存在且引用同一资源。素材更新、全量替换和删除也会反向检查已有画布,不能把仍在使用的资源从素材库中移除或替换成其他资源。登录历史账号时,前端会按资源键补建缺失素材并回写 `assetId`。这项修复复用现有表和 Outbox,不新增结构迁移。
账号文件容量只统计 `ready` 资源,并按 Provider、Endpoint、Bucket、ObjectKey 对同一物理对象去重;上传中或失败记录不占用已存储容量,`session_files` 仍按实际大小计入。后台每小时检查资源生命周期:超过 1 小时的 `pending/failed` 记录,以及超过 24 小时仍没有任何素材、画布、任务或其他业务引用的 `ready` 记录,会在再次校验引用后删除数据库记录并写入 `resource_deletion_jobs`,由幂等 Worker 清理物理对象。
素材状态为 `archived` 时进入回收站。后台按“资源与请求策略”中的 `recycleBinRetentionDays` 定期扫描过期项;`0` 表示永久保留。自动清理与用户手动彻底删除复用同一 service 引用校验和 `resource_deletion_jobs` Outbox,仍被画布、项目、任务或其他业务记录引用的素材不会被删除。

View File

@@ -428,6 +428,13 @@ description: 影策已实现功能的手工验证清单与未确认边界
- [x] 资源引用识别改为显式字段合同,未登记的字段名和自由文本不会被推断为资源引用。
- [x] 后端素材删除改为数据库事务 + `resource_deletion_jobs` Outbox,数据库失败时物理文件保持不动。
- [x] Outbox Worker 本地文件删除、对象不存在幂等成功和失败退避测试通过。
- [x] 画布上传、媒体工具产物、导演台输出、ZIP 导入和时间线直连媒体统一先写入素材库;远端同步按“素材后端确认后再保存画布”的顺序执行。
- [x] 后端保存画布时校验 `assetId`、资源归属、就绪状态和素材资源一致性;素材更新、替换与删除不能破坏已有画布引用。
- [x] 登录会修复历史画布缺失的素材记录与 `assetId`;后台按状态保留期回收无任何业务引用的资源,并通过删除 Outbox 清理物理对象。
- [x] 账号容量只统计 `ready` 资源并按物理对象去重,上传中、失败记录和重复 Resource 行不会形成虚假容量占用。
- [ ] 在个人画布分别上传图片、视频、音频和时间线媒体,刷新后确认 `/assets` 均可见对应素材、画布 `assetId` 不丢失,账号容量只增长一次。
- [ ] 使用修复前已有“画布存在资源但素材缺失”的账号登录,确认素材自动补建并同步;再准备超过 24 小时且无任何引用的孤儿对象,确认后台最终删除资源记录和物理对象、容量同步下降。
- [ ] 模拟资源上传成功后立即断网,确认画布结构不会以缺失素材的状态写入服务端;恢复网络后自动重试完成素材与画布同步。
- [ ] 使用真实 OSS 配置验证对象删除成功、权限失败后的退避重试和多实例租约接管。
- [ ] 浏览器真实环境验证登录快照慢响应期间工作区保持不可写,以及删除后立即刷新不复活素材。