
Cherry Studio 移除应用存储配额警告主进程磁盘空间监控架构解析【免费下载链接】cherry-studio Cherry Studio 是一款支持多个 LLM 提供商的桌面客户端项目地址: https://gitcode.com/CherryHQ/cherry-studio导读本文基于 Cherry Studio 的 breaking-change 记录 2026-06-05-remove-app-storage-quota-warning.md剖析一次存储告警体系的架构调整v2 移除了基于浏览器navigator.storage配额≥95% 触发的误导性应用存储配额警告同时将保留的低磁盘空间警告剩余空间 1 GiB从渲染进程计时器迁移到主进程StorageMonitorService实现容量自适应轮询、共享缓存发布与自动消失。读完你将掌握 v2 磁盘健康检测的完整调用链、阈值与轮询策略、渲染端订阅机制以及该变更对用户与发布流程的实际影响。一、变更背景为什么浏览器存储配额警告不再可靠在 v1 架构中Cherry Studio 的业务数据依赖渲染进程侧的浏览器存储redux-persist及其相关存储方案。因此旧版实现通过navigator.storageAPI 监测浏览器存储使用量当用量达到≥95%时触发应用存储配额警告即本文记录中被移除的checkAppStorageQuota检查。v2 架构发生了根本性变化业务数据改由主进程的 SQLite 数据库统一承载数据目录位于app.userdata路径下。从源码结构看v2 的数据层完全落在主进程侧见 src/main/data渲染进程只消费数据访问 API。这意味着浏览器存储配额已经不再反映数据实际存储的位置——继续沿用 v1 的配额检测会产生误导即使浏览器存储空间充足真实数据所在的磁盘可能已濒临耗尽反之亦然。正因如此该 breaking change 的核心决策是彻底移除checkAppStorageQuota检查用户不会再看到应用存储配额警告同时保留并强化真正有意义的磁盘空间检测。二、变更内容速览维度变更前v1变更后v2检测对象渲染进程浏览器存储navigator.storageredux-persist 等承载用户数据目录的磁盘卷触发条件浏览器存储用量 ≥ 95%数据目录所在卷剩余空间 1 GiB检测位置渲染进程定时器主进程StorageMonitorService轮询策略固定间隔容量自适应5 分钟 ~ 60 分钟警告作用域全局仅主窗口自动消失阈值—保持不变剩余空间 1 GiB其中被移除的只有checkAppStorageQuota这一项检查磁盘空间检测并未消失而是迁入主进程并获得了更可靠的实现详见下文。三、新架构主进程 StorageMonitorService新磁盘监控的核心实现在 src/main/services/StorageMonitorService.ts。该服务通过Injectable(StorageMonitorService)与ServicePhase(Phase.WhenReady)装饰器注册在应用进入WhenReady生命周期阶段后启动并由 serviceRegistry.ts 统一管理。3.1 阈值1 GiB 的科学依据export const STORAGE_LOW_THRESHOLD_BYTES 1 * GB阈值保持 v1 不变剩余空间 1 GiB 触发警告但源码注释给出了设计理由该数值对齐 GNOME 桌面环境的free-size-gb-no-notify1默认值——当剩余空间低于约 1 GiB 时写入操作开始有失败风险。换言之这是一个数据丢失风险临近的警示线而非普通的空间提醒。3.2 容量自适应轮询越危险越频繁export function intervalForFree(freeBytes: number): number { if (freeBytes 20 * GB) return 60 * MINUTE if (freeBytes 10 * GB) return 30 * MINUTE if (freeBytes 5 * GB) return 15 * MINUTE if (freeBytes 1 * GB) return 10 * MINUTE return 5 * MINUTE }intervalForFree将剩余空间划分为 5 个档位轮询间隔从 60 分钟空间充裕到 5 分钟濒临阈值单调且限定在 [5min, 60min] 区间内。这一设计同时满足两个目标及时告警磁盘快速填满时检测频率随之加快及时恢复空间被释放后能以更短的间隔侦测到恢复从而尽快自动关闭警告。scheduleNext()实现了同档位不重建定时器的优化仅当剩余空间跨越档位边界时才销毁旧定时器并按新间隔重新注册避免无谓的定时器抖动该模式与ProxyService一致。注意首次探测是 fire-and-forget 的——onReady()中void this.check()让磁盘检测异步进行绝不阻塞应用启动。3.3 磁盘读数statfs 与可用字节语义const stats await statfs(application.getPath(app.userdata)) this.applyHealth(stats.bsize * stats.bavail, stats.bsize * stats.blocks)服务通过 Node.js 的statfs直接读取用户数据目录所在文件系统的统计信息关键细节有两点使用bavail非特权进程可写入的块数而非bfree因为只有bavail才是用户进程真正能写入的字节量由于types/node的StatsFs类型不含frsize字段代码以bsize作为换算单位。3.4 健壮性错误不翻转状态、定时器永不静默死亡check()的异常处理体现了可靠性设计statfs 瞬时失败不改变警告状态读取失败时保留上一次的健康快照last-known health仅记录错误日志等待下一轮重试无论成败都重新挂载定时器finally块中的scheduleNext()保证即使连续读盘失败监控也不会悄悄停止。3.5 健康快照发布共享缓存每次探测后applyHealth将最新健康状态写入共享缓存application.get(CacheService).setShared(storage.health, this.health)健康快照类型定义在 src/shared/types/storageMonitor.tsexport type StorageHealthLevel ok | low export interface StorageHealth { level: StorageHealthLevel /** Free bytes available to the (non-privileged) process on the user-data volume. */ freeBytes: number /** Total bytes of the user-data volume. */ totalBytes: number /** When this snapshot was taken (epoch ms). */ checkedAt: number }该键值已在共享缓存 Schema 中注册并带有默认值{ level: ok, freeBytes: 0, totalBytes: 0, checkedAt: 0 }见 cacheSchemas.ts。同时服务初始化onInit时即写入初始快照保证渲染端在首次订阅时就能拿到有效数据。四、渲染端订阅与自动消失机制主进程只负责测量并发布展示由渲染进程主窗口完成二者通过共享缓存解耦。核心实现是 src/renderer/hooks/useStorageMonitorNotification.tsconst health useSharedCacheValue(storage.health)该 Hook 通过useSharedCacheValue订阅storage.health并依据状态机驱动警告的显示与自动关闭level low且当前无警告弹出 toast 警告文案来自 i18nsettings.data.limit.appDataDiskQuota/appDataDiskQuotaDescriptiontimeout: 0表示不自动超时关闭并记录warningKey防止重复弹出level ok且存在警告调用toast.closeToast(warningKey)立即关闭警告并清空 key。这一机制保证了本文档描述的用户体验目标低空间通知可靠出现一旦空间释放自动消失。中英文文案示例见 zh-cn.json标题磁盘空间警告 / Disk Space Warning描述数据目录空间即将用尽请清理磁盘空间否则会丢失数据 / Data directory space is almost empty, please clear disk space, otherwise data will be lost五、端到端数据流从源码可以还原完整的运行时链路statfs(app.userdata) 读取磁盘卷 │ ▼ StorageMonitorService.check() / applyHealth() │ 每档轮询间隔由 intervalForFree 决定5~60min ▼ CacheService.setShared(storage.health, StorageHealth) │ ▼ renderer: useSharedCacheValue(storage.health) │ ▼ useStorageMonitorNotification → toast.warning / toast.closeToast自动消失要点归纳检测权归主进程磁盘是主进程拥有的资源单一容量自适应定时器取代了渲染端轮询状态共享靠缓存健康快照通过共享缓存广播到所有窗口但只有主窗口消费并展示警告只服务主窗口作用域收窄避免多窗口重复弹窗。六、测试验证阈值、档位与状态迁移StorageMonitorService.test.ts 用 Vitest 覆盖了关键行为可作为行为契约参考档位映射it.each参数化验证intervalForFree的 10 组边界值如 20 GiB→60min、20 GiB−1→30min、1 GiB→10min、1 GiB−1→5min并断言间隔被限定在 [5min, 60min]生命周期断言服务运行在WhenReady阶段getPhase(StorageMonitorService) Phase.WhenReady状态迁移验证ok → low发布 low 快照、low → ok发布恢复快照供渲染端关闭警告两条关键路径定时器优化同档位不重建定时器跨档位才 dispose 旧定时器并按新间隔注册错误容错statfs抛错时状态不翻转、定时器仍存活。此外渲染端 Hook 的测试useStorageMonitorNotification.test.ts验证了low触发一次警告、连续low不重复弹窗、ok后自动关闭的行为。七、对用户的影响与操作对于最终用户本次变更无需任何手动操作不再出现应用存储配额警告——这是误导性告警已随 v2 数据架构业务数据存入主进程 SQLite而移除磁盘保护保留且更可靠——当数据所在磁盘剩余空间低于 1 GiB 时主窗口会弹出磁盘空间警告提示清理磁盘以免数据丢失警告自动消失——清理磁盘、释放足够空间后警告会在下一次轮询容量自适应间隔后自动关闭无需重启应用。八、发布与维护注意事项对于 release manager 或维护者该变更记录还明确了发布动作本次删除的仅限checkAppStorageQuota检查磁盘空间检测并未移除而是整体迁入主进程StorageMonitorService保留的检测语义为主窗口作用域、容量自适应轮询、自动消失警告阈值保持剩余空间 1 GiB不变合并时需将 frontmatter 中的introduced_in_pr: #TBD更新为实际 PR 编号详见 原变更文档作为 v2 破坏性变更清单的一部分归档。相关文件索引变更记录v2-refactor-temp/docs/breaking-changes/2026-06-05-remove-app-storage-quota-warning.md主进程监控服务src/main/services/StorageMonitorService.ts健康快照类型src/shared/types/storageMonitor.ts服务注册src/main/core/application/serviceRegistry.ts渲染端展示 Hooksrc/renderer/hooks/useStorageMonitorNotification.ts共享缓存 Schemasrc/shared/data/cache/cacheSchemas.ts主进程服务测试src/main/services/tests/StorageMonitorService.test.ts渲染端 Hook 测试src/renderer/hooks/tests/useStorageMonitorNotification.test.ts【免费下载链接】cherry-studio Cherry Studio 是一款支持多个 LLM 提供商的桌面客户端项目地址: https://gitcode.com/CherryHQ/cherry-studio创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考