Lake Baikal:同步不是白给的
六周前,在那篇讲你的书库为什么存在你设备上的文章里,我们轻描淡写地许了一个诺:“同步,在不远的将来。”0.5.0 版——Lake Baikal——就是那个“不远的将来”。距上一个稳定版发布已经过去十八天,这是这个项目有史以来最长的一次沉寂,而这段空档,值得一个解释。
为什么同步是最难兑现的承诺
对一个普通的应用来说,同步只是一项功能。而对一个本地优先的应用来说,它考验的,是你宣称信奉的一切。
我们此前许下的两件事,让同步变得毫不留情。第一,你的数据是端到端加密的:中继服务器存储的只是用一把由你的口令派生的密钥封存的密文,除此之外别无他物。这话听起来像产品页上的一行要点,直到你意识到它的代价——服务器永远不能替你合并数据,永远不能修复它,甚至永远不能看它一眼来帮你调试。每一个难题都必须在你的设备上解决——构造使然。
第二,ReadAware 的存储是一条只追加的事件日志;应用读取的那些表,都是从这条日志重建出来的投影。于是,同步的单位不再是“你的书库表”——而是发生过的每一个事件,且无论哪台设备在离线时写下过什么,它们最终都必须收敛到同一个顺序。让第二台设备重放你的整段阅读生涯、并最终抵达同一个书库,与其说像拷贝文件,不如说更像在证明一条关于你自己过去的定理。
所以 Lake Baikal 走的是那条慢路:混合逻辑时钟负责定序;批量重放,让一大堆积压事件一次性重建投影,而不是每页重放一次;分块上传,让一本 200 MB 的扫描书以可断点续传的碎片上路;从浏览器链接直接唤起应用的登录;再加上一条实时推送通道——你在桌面端划下的一条高亮,还没等你拿起手机,就已经出现在手机上了。甚至连你的偏好设置也会漫游——主题、排版、AI 设置、API 密钥——一次全新安装,一分钟之内就有了你的样子。
幽灵之书
第一次真正的双设备试跑,就产出了这次发布里我们最喜欢的一个 bug:有些书在新设备上只剩下封面,一页正文都没有。幽灵。
结果发现,是三个互不相干的故障叠在一起,叠得整整齐齐,每一个都恰好把下一个遮了个严实。引导流程照抄了清单行,可对应文件的字节根本还没上传完;在其中某个平台上,webview 的安全策略悄无声息地拦住了应用通向中继服务器的路;而当中继服务器因某个文件超出免费档位的大小上限而拒收时,这次拒收也被记了下来——无声地——记在一个没有任何界面会去展示的字段里。三场静默的故障,一个灵异的表象,外加好几天的取证排查。
这次的修复,一半是代码,一半是哲学:同步如今为每一本书配上了面板,哪些已抵达云端、哪些还没有、原因何在,一概亮得明明白白。被允许静默失败的系统,终将静默失败;唯一的解药,是让它的状态变得可见。
幽灵索要的审计
那个“被无声记下的拒收”让我们如鲠在喉,于是等同步一稳定下来,我们便把整个应用的错误处理从头到尾审计了一遍。结果令人汗颜:有十四处把原始的内部错误直接甩到用户脸上,有八处吞掉了用户理应知晓的失败,还有一条迁移路径,竟会在导入失败之后悄无声息地把数据删掉。
Lake Baikal 交付的是一次推倒重来:如今每一次失败都携带一个稳定的错误码,都以一条本地化、可据以行动的讯息示人——绝不会是一串 stack trace——都把“空空如也”与“确实坏了”分得清清楚楚,并且,只有当重试真能帮上忙时,才提供重试。倘若应用当真崩溃了,下一次启动会奉上一份诊断报告(先问过你——绝不自动发送)。
一堵只有一个数组那么长的墙
有位用户报告,Android 无法导入 TXT 文件。我们一头雾水:TXT 支持早在几个月前就上线了。而这两件事,都是真的。格式支持确实住在应用里;那堵墙则立在另一处——一份硬编码的 MIME 类型列表,它被递给 Android 的系统文件选择器,写于 TXT 支持尚未存在之时,此后再未更新。每一台 Android 设备上的每一个 .txt 文件,就这样统统被六行配置灰掉了。
这是本次发布里最具教益的一个 bug:一个功能,不在于代码能做到什么,而在于用户够得着什么。如今,我们把“够得着”也纳入了测试。
湖里还有什么
书籍记忆快了一大截——那张人物与概念图谱,过去要靠几个小时的空闲时间才能慢慢成形,如今却能跟你赛跑:你打开一本书,头几分钟里它就建好了。助手也不再把它钉死在每一条 prompt 上,而是像调用一件工具那样去查询它。现在有两条更新通道(喜欢快车道的话,选 Beta),有一个像样的、标着价格的 OpenRouter 模型选择器,有能给整个应用换主题、还能自我更新并支持回滚的插件,还有鼠标滚轮翻页。
同步功能自带免费档位,书库一旦超出额度,付费方案就会抬高存储上限——说白了,中继就是靠这个养活的。
Lake Baikal 蓄着全世界五分之一的淡水,在一米厚的冰层之下依然不冻,并且悄悄留住了交给它的每一样东西。在这个版本里,你的书库学会了:无论哪一台设备出什么事,它都安然无恙。给这样的版本起这个名字,感觉再合适不过。湖很深。把你的书扔进来吧。