fix: restore sticker placeholders and media history
(cherry picked from commit 488e409a1898e9c739cc0bd24cb9791636dfd6b3)
This commit is contained in:
parent
27970adf46
commit
23a2b2aff7
11 changed files with 225 additions and 165 deletions
|
|
@ -41,6 +41,7 @@ status 取值:done(真实实现) / stub(兼容响应) / todo(已发现未实
|
|||
> 2026-06-03 sticker installed-cache 语义修复:继续对照 TDesktop `Storage::Account::writeInstalledStickers` / `Data::ParseStickersSetFlags` 后确认,`installed_date` 会让 set 进入 Installed;普通 installed stickers 集若仍处于 `NotLoaded`,客户端会中止本地 installed stickers 写入。telesrv seed 过去把 `InputStickerSetAnimatedEmoji` / dice / generic animations 等 system set 也标成 installed,导致系统资源混入普通 installed stickers 缓存路径。现 migration `0066_system_sticker_sets_not_installed` 修复既有库,并改 seed:`set_kind=system` 仅作为按 input 系统 key 解析的内置资源,不再声明为 installed。
|
||||
> 2026-06-03 sticker 静态缩略图元数据修复:继续读 TDesktop `history_view_sticker.cpp` / `data_document_media.cpp` / `data_cloud_file.cpp` 后确认,历史页若看到 document `PhotoPathSize` 会把它当成 vector placeholder,`dataMediaCreated()` 因 `thumbnailPath()` 非空跳过 `thumbnailWanted()`,从而挡住同时存在的真实 raster thumb。seed 现将 ≤32KB 可下载 document thumb 转为 `PhotoCachedSize` 并写入 image cache 所需 bytes;当 document 已有 raster/default/cached/progressive thumb 时丢弃 `PhotoPathSize`,仅没有 raster 的 set cover 继续保留 path 占位;thumb blob MIME 由字节魔数写入,`upload.getFile` 也优先按魔数返回 `storage.fileWebp`,兼容旧库误标 `image/jpeg`。验证:`go test ./internal/app/files -run "TestSeedMediaFromRealExport|TestSeedPreferRasterDocumentThumbsDropsPathWhenRasterExists|TestDocumentsNeedInlineCachedThumbsDetectsPathWithRaster|TestDocumentsNeedInlineCachedThumbsDetectsStaleMime" -count=1`、`go test ./internal/rpc -run "TestStorageFileType" -count=1`、`go test ./... -count=1` 通过;新 server 启动 repair 后 PG `documents.thumbs` kind 分布为 `cached=2313`,两条样例 `5415908822013185960/5381935901284774004` 均仅 `cached/m`,`file_blobs` document thumb MIME 为 `image/webp=2313`;服务进程 PID 53892 监听 2398。
|
||||
> 2026-06-03 sticker 文档身份修复:继续对比 TDesktop `data_session.cpp` / `data_document.cpp` / `history_view_sticker.cpp` 后确认,TDesktop 以 `document_id` 复用 `DocumentData`,且 `DocumentData::updateThumbnails()` 不会清掉旧的 inline/path thumbnail 状态;一旦服务端把外部导出 document id 当成本服资源主键,旧 Debug tdata 中同 id 的污染对象会持续影响历史页渲染。telesrv 现把导出 JSON/文件名中的 document id 只作为 seed source id,在 `internal/app/files` 导入阶段归一为 telesrv-owned storage id;RPC、`InputDocument`、`inputDocumentFileLocation`、`getCustomEmojiDocuments`、channel custom emoji status/reaction/color 均直接使用同一个服务端 document id,不再做边界映射。migration `0067_seed_document_id_namespace` 同步修复既有开发库中的 documents/file_blobs/sticker_sets/available_reactions/message media/channel appearance 引用。document thumb 在 store 中可保留 cached bytes,但 RPC 对 document 统一暴露 downloadable `photoSize m`,避免 `PhotoCachedSize` 与本地旧 cache 组合出不可替换状态。验证:`go test ./internal/app/files -run TestSeedMediaFromRealExport -count=1 -v`、`go test ./... -count=1` 通过;server `bin\\telesrv.exe` 监听 2398,migration 状态 `67|false`,PG `documents/file_blobs/message media/available_reactions/sticker_sets` 均无 `>4e18` 外部 document id;Computer Use 重启 Debug/Alice 与 DebugBob/Bob 后分别打开 Bob B/Alice A,250ms 截图已显示 sticker,server 与两端客户端日志无 `NOT_IMPLEMENTED` / `Unhandled RPC` / `bad_msg` / `LOCATION_INVALID` / `API Error` / sticker hash 异常。
|
||||
> 2026-06-07 sticker 静态图慢复盘 / 撤销 a.2 的 path 丢弃:再读 TDesktop `history_view_sticker.cpp`(`draw→paintPixmap→paintPath` 占位优先级,`thumbnailInline` 内联分支被源码注释禁用)与 `data_document_media.cpp`(`checkStickerLarge→automaticLoad` 下载完整 `.tgs`,与 path/thumbnail 无关)后确认:上方 2026-06-03「sticker 静态缩略图元数据修复」丢弃 `PhotoPathSize` 是误判(真根因是同日 document id 污染,已由 `0067` 修复);id 修复后再丢 path 反而使 animated sticker 失去唯一即时占位 ⇒ 打开会话先空白,并因 `thumbnailPath()` 变空多触发一次缩略图 `getFile`,与完整 `.tgs` 争用下载通道 ⇒「静态图特别慢、不像本地加载」。现 `internal/app/files/seed.go` 恢复 `PhotoPathSize` 占位(删 `seedPreferRasterDocumentThumbs` 及 path+raster stale 判定),document.thumbs = path + downloadable `photoSize m`。已实测排除磁盘 IO/缓存容量(blob 4330 文件 71.3MB,几乎全 ≤64KB)与 `document.Size` 不匹配(28/28 一致)。验证:`go test ./internal/app/files ./internal/rpc -count=1`、`TestSeedMediaFromRealExport -count=1`(真实导出 74 reactions/11 sets/1355 docs/2710 blobs,断言 seed 后 document 保留 path)、`go vet` 通过。**现有库需重新 seed 一次**:`DELETE FROM sticker_sets; DELETE FROM available_reactions;` 重启触发全量 reseed(`PutDocument`/`PutFileBlob` upsert,不删用户上传媒体)。待双 TDesktop 人工验证渲染体感。
|
||||
|
||||
## Transport / MTProto 服务消息
|
||||
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@
|
|||
- **P1-媒体-a `upload.getFile` 整文件入内存 + 每 chunk 查 PG / sticker 小资源首开冷路径** — ✅ **已修(2026-06-03)**:原 `blobs.Get` 一次 `os.ReadFile` 读整个 blob 再切片,客户端按 ≤512KB/1MB 分块多次请求 ⇒ 同一大文件被重复整读 N 次(O(N²))+ 每 chunk 一次 `GetFileBlob` PG 往返;sticker/reaction/thumb 虽小,但 TDesktop 重启或打开历史首次渲染时仍可能在 `messages.getStickerSet` + `upload.getFile` + 本地文件冷读上形成可感知卡顿。现 `BlobBackend.GetRange`/`LocalFS`(`internal/app/files/blobfs.go`)用 `ReadAt` 只读 offset+limit 段(`n` 受文件大小约束,超大 limit 不会按客户端值分配内存);并加 `location_key→FileBlob` 进程内 LRU(容量 65536,元数据不可变故只读填充无需失效)消除每 chunk 的 PG 查;再加 `object_key→bytes` 小 blob LRU(单项 ≤256KB,总 64MB)、完整 sticker set cache 与启动 `WarmCaches`,从已 seed 元数据预热 sticker/reaction document 和可下载缩略图。参考实现 用 MinIO ranged read(`object.ReadAt`)+ SSDB 两级,但其下载命中冷存储不回填、无 LRU/阈值、photo/头像直连 MinIO;telesrv 当前先做进程内元数据/小字节 LRU + 段读,**多实例共享缓存(Redis)仍待二阶段换对象存储时评估**。实测启动预热 `49 sets / 2313 docs / 2298 blobs`,TDesktop `messages.getStickerSet` 从约 18-24ms 降至 0-1.7ms;seed document id 归一后,首次新服务端 id 会触发必要的 `upload.getFile` 主体/缩略图请求,但 server 端大多 0.5-6ms、样例最长 59ms,重复打开 Bob 会话 0.58s 截图已可见 sticker。
|
||||
|
||||
- **P1-媒体-a.1 system sticker set 污染 installed stickers 本地索引** — ✅ **已修(2026-06-03)**:TDesktop 贴纸正文缓存 key 为 `dc_id + document_id`,但 installed stickers 本地索引写入依赖 set flags;`installed_date` 会使 set 进入 Installed,普通 stickers 类型的 `Installed + NotLoaded` set 会让 `writeInstalledStickers()` 中止。此前 seed 把 animated emoji/dice/generic animations 这类 system set 也标成 installed,可能导致重启后 installed sticker 索引反复失效与 set 元数据重拉。现 migration `0066_system_sticker_sets_not_installed` 修复既有库,seed 后续也不再把 `set_kind=system` 声明为 installed。
|
||||
- **P1-媒体-a.2 sticker document 同时暴露 `PhotoPathSize` 与 raster thumb,历史页静态图被占位短路** — ✅ **已修(2026-06-03)**:TDesktop `history_view_sticker.cpp` 在创建 sticker media view 时若 `thumbnailPath()` 非空就不调用 `thumbnailWanted()`,而 `PhotoPathSize` 只是 vector placeholder;此前 seed 给同一 document 同时返回 path + raster thumb,导致历史页持续画 path/等完整 TGS 解码,用户反复重启 Debug 仍看不到静态图。现 document 有 default/cached/progressive raster thumb 时过滤 `PhotoPathSize`,thumb blob MIME 按魔数写入;domain 中可用 cached bytes 做修复依据,但 RPC 对 document 统一暴露 downloadable `photoSize m`,避免 `PhotoCachedSize` 与旧本地 cache 叠加出不可替换状态。启动 repair 后 PG 中 document thumbs kind 仅剩 `cached=2313`,document thumb `file_blobs.mime_type` 全部为 `image/webp`。
|
||||
- **P1-媒体-a.2 历史页 sticker 静态图慢 / 打开会话先空白** — ✅ **已修正(2026-06-07,撤销 2026-06-03 的过度修复)**:根因复盘 — TDesktop `history_view_sticker.cpp` 对 animated sticker 的占位渲染优先级为 `getStickerLarge()`(完整 `.tgs` 首帧,需下载)→ ~~`thumbnailInline()`(stripped 内联,源码显式注释禁用:sticker 需 alpha 通道)~~ → `goodThumbnail()` → 下载的 `thumbnail()` → **`paintPath()`(`PhotoPathSize` 矢量轮廓,内联即时,唯一不依赖下载的占位)** → 空白;且完整 `.tgs` 由 `DocumentMedia::checkStickerLarge()`→`automaticLoad()` 下载,**与 path/thumbnail 无关**。2026-06-03 的 a.2 误把"卡在 path 等完整 TGS"当作 path 短路(真根因是 a.3 的 document id 污染让完整文件下载/缓存失败),改为有 raster 时过滤 `PhotoPathSize`。a.3 修掉 id 后,这个过滤变成净负面:document 失去唯一即时占位 ⇒ 打开会话 sticker 先空白;且 `thumbnailPath()` 变空触发 `thumbnailWanted()` ⇒ 每个 sticker 多下载一次缩略图,与完整 `.tgs` 争用下载通道,几十个 sticker 排队 ⇒ "静态图特别慢、不像本地加载"。现 seed 恢复 `PhotoPathSize` 占位(与官方 sticker 一致,`internal/app/files/seed.go` 不再过滤 path,删 `seedPreferRasterDocumentThumbs`/`documentThumbsHave{Raster,Path}`),document.thumbs = path + downloadable `photoSize m`:打开即时画轮廓占位、有 path 后不再主动下载缩略图、下载通道全给完整 `.tgs`、第二次本地缓存秒显。已实测排除磁盘 IO/缓存容量(blob 4330 文件 71.3MB,几乎全 ≤64KB)与 `document.Size` 不匹配(28/28 一致)。**现有库需重新 seed 一次恢复 path**:`DELETE FROM sticker_sets; DELETE FROM available_reactions;` 后重启触发全量 reseed(`PutDocument`/`PutFileBlob` upsert,不删用户上传媒体)。`TestSeedMediaFromRealExport` 用真实导出验证 seed 后 document 保留 path。**待双 TDesktop 人工验证渲染体感。**
|
||||
- **P1-媒体-a.3 复用导出 document id 命中 TDesktop 旧 `DocumentData` 缓存** — ✅ **已修(2026-06-03)**:TDesktop `Data::Session::document(id)` 按 `document_id` 单例化,`DocumentData::updateThumbnails()` 不会清空旧 inline/path thumbnail;因此 server 修掉坏 thumb 字段后,旧 Debug tdata 仍可能用同 id 的污染对象,打开历史先空白再等完整 TGS。根因是 seed 曾把外部导出 document id 直接作为本服资源主键。现 `internal/app/files` 在导入阶段把 source id 归一为 telesrv-owned storage id,RPC/download/custom emoji/channel appearance 全部直接使用该服务端 id;migration `0067_seed_document_id_namespace` 修复既有库的 documents/file_blobs/sticker_sets/available_reactions/message media/channel appearance 引用。这样不需要改官方客户端,也不在 RPC 层保留客户端特判。复测:migration 后 PG 相关引用均无 `>4e18` 外部 document id;双 TDesktop 重启后打开 Bob B/Alice A 首屏 250ms 已显示 sticker,`messages.getHistory` 约 6-12ms,`upload.getFile` 命中新 id 成功,server/client 日志无 location/hash/API 错误。
|
||||
- **P1-媒体-b `upload_parts` 无 GC / 无每用户配额** — `internal/app/files/service.go:30` + `deploy/migrations/0057_media.up.sql`:分片直接进 PG `bytea`,仅 `assembleUpload` 成功才删;**未 assemble 的分片永久滞留**,且不同 `file_id` 无上限 ⇒ 任意登录用户可用海量 fileID 各传几片撑爆 PG(容量 DoS)。建议每用户 in-flight 上传字节/分片配额 + 后台按 `created_at` 过期清理 worker。
|
||||
- **P1-媒体-c `media` JSONB 内联放大 fan-out 写** — `deploy/migrations/0057_media.up.sql:129`:`media` 快照内联在 `message_boxes`(owner 双份)/`channel_messages`,含 stripped thumb/attributes 使单行变大;叠加主线 A 的 channel 全员写扇出时,大群每条媒体消息按成员数复制整个 media JSONB。建议随主线 A 改懒算/单副本时一并评估 media 是否只存引用、下沉 `documents`/`photos`。
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue