跳至內容

同步演算法

Mindwtr 採用在地優先同步,並以確定性方式處理衝突。

本頁是供維護與除錯使用的技術合併參考。面向使用者的後端設定、復原步驟與操作指南,請參閱資料與同步

輸入與輸出

  • 輸入 A:本機快照(tasksprojectssectionsareassettings
  • 輸入 B:遠端快照(相同形狀)
  • 輸出:合併快照 + 合併統計(conflictsclockSkewtimestampAdjustmentsfutureTimestampClampsconflictIdsconflictReasonCountsconflictSamplestimestampAdjustmentIdsfutureTimestampClampIds),另加有界同步診斷日誌。

快照式傳輸

Mindwtr 目前透過合併完整快照來同步。這是刻意採用的設計,不是尚未建置的 delta 層。

  • ADR 0003 與 ADR 0007 定義在快照承載資料上執行的修訂版本感知合併行為。
  • ADR 0008 記錄保留快照同步、延後 append-only delta 日誌的傳輸決策。
  • ADR 0009 記錄 SQLite 至 JSON 橋接合約:SQLite 是主要本機儲存區,data.json 則是同步/備份快照。
  • 以目前規模而言,相較於重播及壓縮各裝置的操作日誌,這能讓同步保持不可分割,也更容易推理。

只有在快照檔案經常超過 5 MB、一般網路上的同步往返超過 5 秒,或 Mindwtr 需要即時多裝置串流時,才應重新檢視 ADR 0008。屆時 delta 設計應擴充現有 revrevBy 中繼資料,而不是另建一套平行序列機制。

合併規則

  1. id 比對實體。
  2. 實體只存在一側時,予以保留。
  3. 兩側皆存在時,使用修訂版本感知 LWW 合併:
    • 有修訂版本中繼資料時,先比較 rev(較高者勝出)。rev 是每個實體的編輯計數器,不是 vector clock,因此一部裝置上的多次離線編輯,可能勝過另一部裝置上一次較新的編輯。
    • 修訂版本相同時,比較 updatedAt(較新者勝出)。
    • 時間戳記相同時,若兩側有不同裝置 ID,依字典順序比較 revBy,再以正規化內容簽章進行確定性平手裁決。revBy 步驟不是裝置優先順序,而是在內容簽章備援執行前,讓每個 peer 對相同修訂版本、相同時間戳記的衝突收斂至相同勝方。
    • 沒有修訂版本中繼資料的舊版實體,會將 5 分鐘時鐘偏差閾值內的 updatedAt 視為模糊平手,並採用確定性簽章勝方。超出該範圍則由較新的 updatedAt 勝出。
  4. 軟刪除使用操作時間:
    • 刪除標記的操作時間 = max(updatedAt, deletedAt)
    • 使用中與已刪除的衝突,由較新的操作時間勝出。
    • 若刪除與使用中操作時間相差不超過 30 秒,且修訂版本號相同,Mindwtr 會保留使用中項目,而不讓刪除標記立刻勝出。這是刻意設計的模糊時間範圍規則,可能讓剛刪除的任務在另一部裝置同時編輯後再次出現。
    • 在該 30 秒範圍內,若修訂版本不同,仍由較高修訂版本勝出。
    • 沒有修訂版本中繼資料的舊版記錄,在同一時間範圍內以刪除標記優先。
    • 備份還原是模糊時間範圍之外唯一刻意設計的例外:若使用中一側的 revBy = "backup-restore",且其操作時間不早於刪除標記,則由還原的使用中項目勝出。
    • 刪除勝過使用中編輯時,Mindwtr 會輸出一筆有界 syncConflictDiscarded 診斷項目,包含實體類型、ID、操作時間與修訂版本中繼資料。
    • 保留模糊時間範圍內的使用中項目時,Mindwtr 會輸出一筆有界 Preserved live item during ambiguous delete-vs-live merge 診斷項目,並在同步歷史/設定中儲存衝突中繼資料。
  5. 無效 deletedAt 會退回使用 updatedAt,採用保守操作時間。
  6. 附件依附件 id,採用相同 LWW 規則合併。
  7. 專案歸檔還原中繼資料是不透明的同步中繼資料:
    • 歸檔專案時,會在歸檔動作所變更的任務與分區上記錄暫時還原中繼資料。
    • 可比較與確定性同步簽章會忽略此中繼資料,因此單是歸檔簿記不會產生內容衝突或確定性勝方。
    • 取消歸檔只會還原仍符合歸檔所產生變更的記錄。已刪除、手動修改或移至其他專案的任務會原樣保留,且可能保有不透明中繼資料,直到下一次因真正的使用者或同步變更而重寫該記錄。
  8. 領域使用刪除標記:
    • 刪除領域時只會為領域本身建立刪除標記。該領域中仍使用中的專案與任務會解除連結(以新的修訂版本清除 areaId)並保持使用中。刪除領域永遠不會刪除子項目。
    • 還原領域不會重新連結先前已解除的子項目;它們會保持使用中但沒有領域。
    • 若傳入快照參照缺少或已刪除的領域,同步修復會清除過時的 areaId 參照並標記修復修訂版本。
    • 同步修復也會在刪除標記上執行,因此已刪除專案/任務日後還原時,不會保有過時的領域連結。
    • 缺少的領域順序值會在合併時合成,並標記 revBy: "sync-repair",避免修復持續遭 peer 覆寫。
  9. 依同步偏好合併設定:
    • 外觀/語言/GTD 排程/外部行事曆/AI/已儲存篩選條件可個別合併。
    • 衝突解決使用群組層級時間戳記(appearancelanguagegtdexternalCalendarsaisavedFilters)。
    • 同一群組內不同欄位的同時編輯,仍可能收斂至較新的群組更新。
    • 已儲存篩選條件依篩選條件 id 合併。使用中與使用中的已儲存篩選條件衝突,會嚴格使用篩選條件的 updatedAt;只有時間戳記相同或無法使用時,才以確定性方式平手裁決。
    • 某群組在本機 syncPreferences 中選擇不參與同步,會雙向生效:Mindwtr 不會將該群組傳至遠端,也不會接受傳入的遠端變更。
    • 密鑰(API 金鑰、本機模型路徑)永遠不會同步。
  10. 遠端寫入復原是明確流程:
  • 本機資料會先寫入並帶有 pendingRemoteWriteAt
  • 遠端寫入成功後清除旗標。
  • 遠端寫入失敗後,會以指數退避安排重試,從 5 秒增加至最多 5 分鐘。
  • 遠端寫入重試失敗 12 次後,Mindwtr 會將同步標示為 error 並顯示後端失敗,而不是無限重試。
  • 裝置本機同步診斷會保留在本機,遠端寫入前會移除。
  1. 時鐘偏差遙測:
  • 合併統計會記錄觀察到的最大偏差。
  • 偏差超過 5 分鐘時顯示警告。
  • 超出合併時時鐘 5 分鐘以上的未來 updatedAt 值,會在比較時限制上限,並計入 futureTimestampClamps
  • 同一筆記錄的兩側皆受未來時間限制時,Mindwtr 會輸出有界 Both merge candidates had future updatedAt timestamps clamped 診斷項目,包含記錄 ID 與限制時間。
  1. 同步期間的本機編輯不會採用硬性鎖定:
  • 桌面版與行動版會偵測本機狀態是否在同步寫入階段發生變更。
  • 發生時會中止目前週期並排入全新同步,而不是覆寫較新的本機快照。

虛擬碼

text
read local
read remote
validate payload shape
normalize entities (timestamps, revision metadata)

for each entity type in [tasks, projects, sections, areas, people]:
  index local by id
  index remote by id
  for each id in union(localIds, remoteIds):
    if only one side exists: keep it
    else:
      winner = resolveWinner(localItem, remoteItem)
      mergedItem = mergeConflict(localItem, remoteItem, winner) // attachments/settings-specific logic
      push mergedItem

merge settings by sync preferences
validate merged payload
write local
write remote
record sync history and diagnostics

衝突範例

範例 1:使用中與已刪除

  • 本機:任務 t110:01 更新,未刪除
  • 遠端:任務 t110:03 刪除
  • 結果:已刪除版本勝出(10:03 操作時間較新)

範例 1b:模糊的刪除與使用中衝突

  • 本機:任務 t110:00:05 編輯,仍為使用中
  • 遠端:任務 t110:00:20 刪除
  • 兩筆記錄的修訂版本號相同
  • 結果:兩項操作只相差 15 秒,且修訂版本中繼資料在模糊時間範圍內相同,因此使用中項目勝出

範例 2:相同修訂版本與時間戳記

  • 本機與遠端的 rev=4updatedAt=10:00
  • 內容不同(titletags 等)
  • 結果:確定性簽章比較會在所有裝置上選出同一勝方

範例 3:無效 deletedAt

  • 本機刪除標記的 deletedAt="invalid-date",且 updatedAt=09:30
  • 遠端使用中項目的 updatedAt=10:00
  • 結果:無效刪除會退回使用 updatedAt09:30),因此使用中項目勝出

附件

  • 中繼資料合併會在檔案傳輸協調之前執行。
  • 勝方附件的 URI/本機狀態可用時會予以保留。
  • 若勝方沒有可用本機 URI,合併可退回另一側的 URI/狀態。
  • 附件刪除與使用中的競爭會採用和任務/專案相同的合併與 syncConflictDiscarded 診斷,因此已刪除附件勝過同時進行的中繼資料編輯時,可在診斷中看見。
  • 缺少的本機檔案會在之後由附件同步/下載處理。
  • settings.attachments.pendingRemoteDeletes 記錄本機刪除附件後,仍須從遠端刪除的檔案。
  • 待遠端刪除項目會保留到遠端刪除成功,不會隨時間清除,因為成功前丟棄項目可能讓已刪除檔案孤立在後端。
  • Mindwtr Cloud 也提供經驗證的孤立項目清理端點,刪除目前快照未參照的附件檔案。

雲端伺服器合併

/v1/data 而言,Mindwtr Cloud 不是單純的物件儲存區。收到經驗證的 PUT /v1/data 時,伺服器會讀取現有命名空間快照、對傳入快照執行相同合併演算法、驗證合併結果,再寫入該結果。

操作影響:

  • 推送完整快照不等於強制覆寫。修訂版本較高、操作時間較新或刪除標記勝出的現有遠端記錄,都可能在 PUT 後保留。
  • 伺服器端參照修復可能產生連鎖更新,例如為已刪除專案下的分區建立刪除標記。
  • 伺服器產生的修復時間戳記使用伺服器實際時鐘,避免快了的用戶端時鐘提前伺服器修復中繼資料。
  • 成功的 PUT /v1/data 回應包含 { ok: true, stats, clockSkewWarning },讓用戶端與測試檢查伺服器採用的合併結果。

快速未變更檢查

雲端用戶端可在下載完整快照前發出 HEAD /v1/data。伺服器會回傳 ETagLast-ModifiedContent-Length 中繼資料,但不含回應本文。用戶端將該中繼資料與上一次成功同步比較;遠端命名空間未變更時,即可略過完整 GET /v1/data 路徑。

伺服器會依檔案 stat 中繼資料快取 SHA-256 ETag,因此重複進行未變更的 HEAD 檢查時,不必重新雜湊整份快照。

排程背景同步

行動版背景同步採用保守的 15 分鐘最短間隔。背景任務只在需要時才延遲載入匯入程式/同步程式碼,再執行上述相同的快照合併與遠端寫入重試邏輯。

背景同步是否執行取決於環境:作業系統可能延遲或略過一次執行,因此連線或憑證變更後,手動同步與前景同步仍是可靠的復原方式。

重試復原

  • 遠端寫入失敗不會默默丟棄剛合併的本機狀態。
  • pendingRemoteWriteAtpendingRemoteWriteRetryAtpendingRemoteWriteAttempts 儲存在本機。
  • 下一次同步會暫停至重試時間範圍屆滿,再使用保留的本機快照與任何較新的本機編輯重試。
  • 重試 12 次後,同步狀態會變成 error。保留的本機快照仍留在本機,狀態介面應引導使用者檢查後端連線或憑證。

刪除標記清除界限

刪除標記只有在保留期間內能保護刪除操作。目前的保留政策受 tombstoneRetentionDays 限制。

在實際操作上,離線時間超過保留範圍的裝置,可能重新帶入其他裝置上已清除刪除標記的記錄。Mindwtr 將此視為快照同步已有文件記載的一致性界限。使用者在依賴長期離線的舊本機資料前,應先同步該裝置;若未來協定需要更嚴格的保證,則應拒絕上次成功同步早於清除範圍的快照。

可檢查的診斷資訊

  • 衝突數量與 ID
  • 衝突原因數量與有界衝突範例
  • 觀察到的最大時鐘偏差
  • 時間戳記正規化調整
  • 時間戳記已正規化的記錄 ID
  • 未來時間戳記限制數量與 ID
  • 使用中一側在刪除與使用中衝突中遭捨棄時的 syncConflictDiscarded 項目
  • 設定中的上次同步狀態/歷史
  • 設定 → 同步中的個別衝突詳情:受影響項目名稱、不同的欄位,以及哪部裝置的版本勝出(限制為最近的範例)
  • 即使除錯日誌關閉,也會寫入 mindwtr.log 的衝突摘要(只含 ID 與欄位名稱,絕不包含記錄內容)

相關文件

疑難排解

若反覆出現衝突或偏差警告:

  1. 檢查裝置時鐘(啟用網路自動校時)。
  2. 檢查同步後端連線/驗證。
  3. 查看應用程式設定與日誌中的同步診斷資訊。

Mindwtr 是免費、開放原始碼且在地優先的應用程式。
Getting Things Done 與 GTD 是 David Allen Company 的註冊商標。Mindwtr 與 David Allen Company 無關,亦未獲其背書或贊助。