跳转到内容
⌂ 回到首页

ECHO Next Native Worker Ready Architecture

Library Core v0.1 从设计上就预留了 native worker 接口。TypeScript 管编排、SQLite、IPC 校验、分页 API、扫描任务和面向 UI 的业务规则;重活通过稳定的 worker 接口调用,以后 Rust 或 C++ 可以替换首批 TS 实现,而不用动 Renderer、IPC 或 SQLite schema。

曲库重活(读标签、抽封面、扫文件夹)怎么分层,以及以后怎么无痛换成原生实现。技术细节多,但核心就一句:接口稳定,实现可换。

稳定接口在 src/main/library/workers/ 下:

  • MetadataReader.read(filePath) -> MetadataResult
  • CoverExtractor.extract(filePath, options) -> CoverResult
  • FileScanner.scanFolder(folderPath, options) -> AsyncIterable<ScannedFile>

当前实现:

  • TsMetadataReadermusic-metadata,优先读嵌入标签,缺字段才用文件名/文件夹兜底
  • TsCoverExtractor:TS+sharp v0.2 封面 worker;嵌入封面、同目录 cover/front/folder 图、生成默认图、磁盘缓存路径、真实 resize 输出
  • TsFileScanner:递归枚举文件并 stat

以后可以换成:

  • RustMetadataWorker
  • RustCoverWorker
  • RustFileScanner

LibraryServiceScanJobQueue 依赖接口,不依赖 TS 具体类。Renderer 和 preload 不知道当前跑的是哪套 worker。

MetadataResult 包含:

  • 规范化 metadata 字段
  • fieldSources
  • 有的话带上嵌入封面字节,给 cover worker 用
  • warnings
  • errors
  • status

CoverResult 包含:

  • source
  • thumbPath
  • albumPath
  • largePath
  • originalRef
  • sourceHash
  • mimeType
  • warnings
  • errors

ScannedFile 包含:

  • path
  • sizeBytes
  • mtimeMs

这些结构是 native worker 必须遵守的契约。原始解析细节可以留在 worker 结果里做诊断,但 Renderer 列表 API 收不到它们。

原生化的优先顺序:

  1. CoverWorker:只有 TS+sharp v0.2 实测达不到封面生成目标时,才最高优先。
  2. MetadataWorker:第二优先;大曲库上标签解析可能变贵。
  3. FileScanner:只有 3000/10000 曲压力测试证明 TS 目录遍历是瓶颈时,才上 Rust/C++。

音频输出已经在走同一条路,通过 echo-audio-host

TypeScript 服务层:

  • 创建扫描任务
  • 检查增量缓存 key
  • 带并发限制调度 worker 调用
  • 事务写 SQLite
  • 持久化专辑和艺术家索引
  • 暴露分页、IPC 安全的结果

Worker 层:

  • 读标签
  • 提取/缓存封面;当前 TS+sharp v0.2 用 sharp 做 resize,优先级和缓存调度仍由 TypeScript 管
  • 枚举文件和 stat 数据

IPC:

  • 校验输入
  • 调用 LibraryService
  • 不跑 SQL、不解析 metadata、不抽封面、不扫文件夹

Renderer:

  • 调 typed preload 方法
  • 渲染分页的 tracks/albums/folders/status
  • 不分组专辑、不生成封面、不扫文件、不把全库塞进内存

Phase 1 和 Phase 1.5 验证目标:

  • 应用启动不能扫全库
  • getTracks 首页目标:200 ms 以内
  • getAlbums 首页目标:300 ms 以内
  • 未变化文件的扫描跳过率应接近 100%
  • 封面缩略图在扫描时生成,不在 UI 滚动时生成
  • 专辑墙重启后读持久化的 albums
  • getTracksgetAlbums 永远不返回完整封面 binary/base64
  • 扫描任务后台跑,且可取消
  • metadata 和 cover worker 有并发限制
  • 大曲库不能因为专辑墙在渲染就把 CPU 顶到 50% 附近

Phase 1.5 Native Worker & Performance Validation:

  • 决定要不要上 native worker 前,先用 Phase 1.1 的 library.getDiagnostics()、烟测和 npm run benchmark:library 结果
  • 只有实测证明封面提取/缓存生成是瓶颈时,才做 Go/C#/Rust CoverWorker
  • 评估 Rust MetadataWorker
  • 跑 3000 和 10000 曲压力测试,以及 3000 和 10000 专辑墙压力测试
  • 记录 CPU、内存、总扫描时间、metadata 时间、封面时间、专辑墙加载时间
  • 用数据决定 FileScanner 要不要 Rust/C++
  • 验证换 worker 不改变 Renderer、IPC、SQLite schema 或列表 payload

Native CoverWorker 决策信号:

  • 生成 1000 张专辑缩略图时 CPU 长时间高于 50%
  • 生成 3000 或 10000 张封面时内存峰值不可接受
  • Electron 里 sharp 打包或 native rebuild 不稳定
  • thumb.webpalbum.webp 已经有了,封面缓存命中仍然慢