# 相册缩略图"小红叉"问题修复记录（2026-09-10）

## 现象
- ComfyUI 出图后，相册能很快拉到图并在界面占位，但缩略图位置显示**加载失败的小红叉**。

## 定位
1. 复现：对最新条目首次请求 `/thumb/<id>.jpg` → **HTTP 500**（body 为 "thumb"），第二次请求才 200 出图。
   - 即：缩略图**首次生成失败**时服务端直接返回 500，浏览器立刻显示小红叉；而生成是"按需触发"，用户看到的正是首次触发的失败。
2. 手动跑 ffmpeg 3 次全部成功（exit 0）、磁盘充足 → 不是 ffmpeg 或磁盘问题，是**服务端偶发生成失败/请求被长队列阻塞**：
   - 偶发 ffmpeg 退出非零（原因待后续日志确认）；
   - 重启后后台预热队列（368 条）会排在新图请求前面，用户实时请求可能等数十秒。
3. 原 `doThumb` 不记录 ffmpeg stderr，失败原因不可见。

## 修复（comfyui-gallery/server.js，已重启生效）
1. **服务端生成失败自动重试**：doThumb 失败后最多重试 2 次（间隔 800ms），并**记录 ffmpeg stderr** 到 web 日志（后续再失败可直接看到原因）。
2. **用户实时请求插队**：`ensureThumb(..., prio=true)` 时 `unshift` 到队列头部，优先于后台预热任务，重启后新图不再被几百条预热任务堵住。
3. **浏览器端失败自愈**：`img.onerror` 自动重试最多 3 次（600ms/1.2s/1.8s 退避，带 `?r=N` 防缓存），即使服务端偶发 500 也不再永久小红叉。

## 验证
- 顺序 10 轮"删缩略图→请求"：10/10 HTTP 200，无失败、无重试日志。
- 并发 8 个条目同时请求：8/8 HTTP 200，缩略图全部生成，0 缺失。
- 页面客户端脚本语法校验通过。

## 终版方案（2026-09-10 追加）：缩略图就绪后才占位（根治）

### 问题复盘
此前"首请求才生成缩略图"存在竞态：条目先出现在网格里，浏览器随即请求缩略图，若此刻生成尚未完成/偶发失败 → 500 → 小红叉。重试机制只能减轻，不能根除"看到红叉"。

### 终版方案（按用户提议：先生成缩略图，确认就绪后再在界面占位）
1. **服务端标记就绪状态**：`/api/catalog` 每条数据新增 `th` 字段（`data/thumbs/<id>.jpg` 是否存在）。
2. **未就绪条目不请求图片**：`th=false` 的卡片渲染为"⏳ 缩略图生成中"占位（**不含 `<img>`**，不发起请求 → 不可能出现小红叉）。
3. **就绪后自动换图**：前端列表签名加入 `pending:` 未就绪数量；后台预热把缩略图生成好后，`th` 翻转 → 签名变化 → 网格自动重绘为真缩略图。
4. **后台增量预热 5s 一轮**：新同步条目的缩略图在 meta 写入后 ≤5s 内开始生成（并发 3，单张 ~0.3s），通常 1~8s 内就绪；失败条目 5 分钟冷却防刷。
5. 兜底仍在：按需生成（用户请求时）带 2 次内部重试 + stderr 日志；浏览器端 onerror 每 2s 重试 ×8。

### 验证
- 删掉最新条目缩略图 → catalog 立即 `th=false` → 8 秒后 `th=true`，缩略图请求 200 出图（640x1134 JPEG）。
- 页面含占位/签名逻辑，客户端脚本语法校验通过。
