跳转到内容

同步

bae 的同步是 coven 的同步:bae 声明自己的表和 blobs,其余由 coven 处理。本页说明这些机制如何应用到 bae;coven 自己的文档会完整覆盖每个部分。

coven 拥有 SQLite 连接,因此 bae 提交的每次写入都会经过它。SQLite 的 session extension 精确记录每个 transaction 中发生了什么变化;同步表上的更改会成为一个 changeset,用资料库 key 封装,并用设备身份 key 签名。没有 diffing,没有 dirty flags:捕获是连接的属性,写入不会被漏掉。

每台设备都会把自己的 changesets 追加到云端主目录中的专属 stream,按顺序编号。设备永远不会写入彼此的 stream,因此存储中没有写冲突;每台设备为每个 peer stream 跟踪一个 cursor。一次同步循环会先 push 本地 outbox,然后从每个 peer 的 cursor 往后 pull 其 stream,并在应用前验证每个 changeset 的签名和作者成员资格。

该循环在本地更改后、带退避的空闲定时器上(poll 间隔最多五分钟),以及点击 Sync Now 后立即运行。失败会退避并重试;循环会把每次结果作为状态、错误文本和应用的行数报告给 UI。

两台设备分开时编辑同一个资料库是正常情况,不是例外。当它们的更改相遇时:

  • 不同行或不同列的编辑都会应用。在笔记本上编辑发行年份,在桌面上编辑其厂牌,会得到两者。
  • 同一行同一列的编辑由该行的 _updated_at hybrid logical clock 排序:较晚编辑获胜,并且每台设备上结果确定且相同。
  • 删除胜过并发编辑:一个设备删除的发行会保持删除,即使另一个设备在同一间隔内编辑过它。

没有冲突 UI,因为没有未解决状态:无论应用顺序如何,每台设备都会收敛到同一结果。

加入或恢复的设备不会从头回放历史。它会下载一个 snapshot,即定期发布到云端主目录的完整 SQLite 镜像,然后只应用每个流在它之后积累的 changeset。快照元数据会记录架构版本以及其中包含的各流游标。

bae 的架构通过编号阶梯迁移,阶梯顶端会标记在设备写入的每个 changeset 上。设备如果拉取到来自更新架构的 changeset,会暂停该流,不应用它之后的任何内容,直到应用更新;没有内容丢失,也不会错误应用。数据库文件本身会拒绝被架构更旧的二进制程序打开。

比架构版本更大的单位是 兼容时代:编译进每个二进制程序的固定 coven 修订版。两个构建只能在同一时代内同步;coven 传输格式的兼容性破坏会产生新的时代,并让每个应用的主版本增加。1.0 之前,每个构建都是时代 0,格式可以无迁移变化。

在不透明主目录中,提供商存储密文 changeset、密文 blob 和已签名成员资格记录;它可以计数对象、观察大小和时间,但无法读取内容。设备拉取的每个对象都会在触碰数据库前被验证,包括签名和成员资格:存储只是一个被动且不可信的信箱。见加密身份和成员资格