Files
TrueGrowth/docs/MEDIA_CACHE_WARNING_LESSONS.md

125 lines
6.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 媒体缓存失败提示经验
## 背景
部分远程图片/视频资源可以被浏览器直接预览,但由于 CORS、opaque response、签名 URL、响应体不可读或存储异常前端无法稳定写入浏览器缓存。此时如果原始链接带有效期用户后续可能丢失素材。
## 经验
1. 判断应以缓存结果为准,而不是以模型、供应商或域名为准。
- 同一类缓存失败可能发生在任意供应商。
- 按模型名硬编码会误报,也会漏掉未来新增模型。
2. “可预览”不等于“已离线保存”。
- `<img>` / `<video>` 能展示远程 URL不代表 Cache Storage 或 IndexedDB 有可恢复副本。
- UI 需要把“仍依赖原始链接”显性化。
3. 列表渲染阶段不能批量跨域探测。
- 素材库和任务队列可能有大量媒体。
- hover 提示和角标应基于已有缓存状态、缓存失败元数据或本地 Cache API 查询,不应为每个资源额外发起网络请求。
4. 缓存元数据和实际缓存体要分开判断。
- IndexedDB 中存在任务元数据,不代表 Cache API 中存在响应体。
- `isCached` 应同时确认元数据和实际缓存体,否则会给用户错误安全感。
5. 失败原因要短、稳定、可展示。
- 用枚举记录机器可判断的原因,如 `cors_opaque``network_error``http_error``storage_error``cache_missing`
- 文案面向用户:资源未能缓存到浏览器,原始链接可能过期,请尽快下载保存。
6. 成功缓存优先级最高。
- 一旦确认资源已写入浏览器缓存,就不应再显示“需下载”角标。
- 避免把历史失败状态长期误导为当前风险。
7. 远程 URL 是结果数据源,缓存只是加速层。
- `http(s)` 结果即使缓存成功,也应继续保留原始 URL。
- Service Worker 可以用规范化后的原始 URL 命中 Cache Storage不需要把任务结果或素材 URL 改成 `/__aitu_cache__/...`
- 只有 `data:` / 原始 base64 这类没有可重放 URL 的内容,才需要落到稳定虚拟路径。
8. 自动清缓存必须极度谨慎。
- Cache Storage 里混有用户资产,不能因为一次 `Cache.put()` 失败就自动 LRU 清理、腾空间、重试。
- 缓存写入失败时,应保留原 URL、记录 `cacheWarning`、让 UI 提醒用户下载,不应主动删除任何媒体缓存。
- 只有程序崩溃、页面无法进入,并且明确判断清缓存能恢复入口时,才允许提供受控清缓存路径;优先要求用户确认,并尽量缩小清理范围。
9. 缩略图是兜底预览,不是原图存在证明。
- `thumbnail=small` 命中只说明 `drawnix-images-thumb` 有预览图,不说明 `drawnix-images` 仍有原图响应体。
- 原图缺失时不要自动删除缩略图;缩略图仍可帮助用户识别素材。
- 但应标记原图缓存缺失,让“需下载”在首次发现风险时出现。
## 推荐做法
- 在缓存服务中标准化 `cacheWarning`,由失败路径生成。
- 在任务结果和素材对象中透传 `cacheWarning`
- 素材库和任务队列只读取本地缓存状态与警告元数据展示角标。
- hover 只展示原因和下载建议,不做实时网络检测。
- 远程媒体缓存成功与否不改变结果 URL只把缓存结果作为 SW/Cache API 的读取优化。
- 禁止把“缓存失败”作为自动清理用户媒体缓存的触发条件。
## 画布虚拟图片 URL 兜底经验
更新日期2026-04-26
### 现象
复制图片粘贴到画布后,图片元素会短暂出现,然后变成加载失败状态,严重时还会被自动删除。
控制台现象通常是:
- `/asset-library/content-xxx.png``<img>` 加载失败
- 但通过页面侧 Cache API 可以读到对应 blob
- 说明资源并非没有缓存,而是虚拟 URL 的响应链路没有喂给 DOM 图片
### 根因
这类问题不要只按“缓存丢失”判断。实际可能是:
- 图片写入了 IndexedDB 元数据,但 Cache Storage 没有实际响应体
- 当前页面没有被新版 Service Worker 接管,`/asset-library/...` 请求落到服务器并 404
- Service Worker 查询缓存 key 与页面写入 key 不一致
- DOM `<img>` 请求 `/asset-library/...` 失败,但应用代码直接 `getCachedBlob(url)` 能成功
如果图片组件在第一次 `onError` 时直接删除元素,就会把“可恢复的展示问题”误处理成“资源不存在”。
### 修复原则
1. 虚拟 URL 首次加载失败不能立即删除画布元素。
- 先重试,最后再确认 Cache Storage 中是否确实没有 blob。
- 只有确认资源不存在时,才允许删除元素。
2. 画布元素必须保存和渲染稳定虚拟 URL。
- 本地图片粘贴后应写入 `/asset-library/content-...`
- 降级路径可以使用 `/__aitu_cache__/image/content-...`
- 不要把长期展示 `src` 改成 `blob:`,否则刷新、协作、恢复和清理逻辑都会失去稳定引用。
3. 修复点应落在 Cache Storage 与 Service Worker 的一致性上。
- 写入缓存前统一规范化虚拟 URL key剥离 `_retry``bypass_sw``thumbnail` 等控制参数。
- SW 读取时同时兼容 pathname、去控制参数后的完整 URL、当前请求 URL。
- 页面侧 `getCachedBlob` 也要按同一规则查询。
4. `objectURL` 只能用于临时读尺寸或预览。
- 使用后要立刻 `URL.revokeObjectURL`
- 不要作为画布图片元素的最终 URL。
5. 调试日志要及时撤掉。
- 定位时可以临时记录 URL、元素 ID、blob size。
- 修复完成后,正常恢复路径不应刷 `warn``info`
- 只保留真正不可恢复或会影响用户数据的异常日志。
### 经验规则
- “DOM 加载失败”不等于“缓存不存在”。
- “Cache 元数据存在”也不等于“Cache 响应体存在”。
- 画布素材展示要以“可恢复”为优先,避免误删用户内容。
- 虚拟 URL 链路坏了要修 SW/Cache key不要用 `blob:` 掩盖主链路问题。