同步
bae 的同步是 coven 的同步:bae 宣告自己的表與 blob,coven 處理其餘工作。本頁說明這些機制套用到 bae 時的樣子;coven 自己的文件完整涵蓋各個部分。
coven 擁有 SQLite 連線,因此 bae 提交的每次寫入都會經過它。SQLite 的 session extension 精確記錄每個 transaction 中變更了什麼;同步表上的變更會成為 changeset,以資料庫金鑰封存,並以裝置身分金鑰簽署。沒有 diffing,沒有 dirty flag:捕捉是連線的屬性,寫入不可能被漏掉。
每個裝置會把自己的 changeset 附加到雲端主目錄中自己的 stream,並依序編號。裝置永遠不寫入彼此的 stream,因此儲存中沒有寫入衝突,每個裝置也會追蹤每個 peer stream 的游標。同步循環會推送本機寄件匣,然後從每個 peer 的 stream 游標往前拉取,驗證每個 changeset 的簽章與作者成員資格後再套用。
循環會在本機變更後、帶退避的閒置計時器上(輪詢間最多五分鐘),以及按下 Sync Now 時立即執行。失敗會退避並重試;迴圈會把每次循環的結果回報給 UI,包括狀態、錯誤文字與套用的列數。
兩台裝置分開時編輯同一個資料庫是正常情況,不是例外。當它們的變更相遇時:
- 對不同行或不同欄的編輯都會套用。在筆電上編輯發行版本年份,同時在桌面上編輯其廠牌,會得到兩者。
- 對同一列同一欄的編輯會依該列的
_updated_athybrid logical clock 排序:較晚的編輯勝出,且每個裝置上結果都確定且相同。 - 刪除勝過並行編輯:一台裝置刪除的發行版本,即使另一台裝置在同一段時間編輯過它,仍會保持刪除。
沒有衝突 UI,因為沒有未解決狀態:無論套用順序如何,每個裝置都會收斂到相同結果。
加入或還原的裝置不會從頭重放歷史。它會下載 snapshot,也就是定期發布到雲端主目錄的完整 SQLite 映像檔,然後只套用各流在其後累積的 changeset。快照中繼資料會記錄架構版本,以及它包含的各流游標。
bae 的架構會沿著編號階梯遷移,階梯頂端的編號會標記在裝置寫出的每個 changeset 上。裝置若拉到比自己更新架構的 changeset,會停放該流,之後的內容都不套用,直到 App 更新;沒有內容遺失,也沒有內容被錯誤套用。資料庫檔案本身會拒絕由比其架構舊的二進位程式開啟。
比架構版本更大的單位是相容時代:烘焙進每個二進位程式的固定 coven 修訂版。兩個建置只能在同一時代內同步;coven 傳輸格式破壞相容就是新的時代,並使每個 App 的主版本增加。1.0 前,每個建置都是時代零,格式變更不做遷移。
提供者能看到什麼
Section titled “提供者能看到什麼”在不透明主目錄上,提供者儲存密文 changeset、密文 blob 與已簽署成員資格記錄;它可以計算物件數量、觀察大小與時間,但不能讀取內容。裝置拉取的每個物件都會先驗證簽章與成員資格,才會碰到資料庫:儲存空間是被動且不受信任的信箱。請見加密與身分與成員資格。