Baku Hashimoto

レプリケーションのマージ戦略

このドキュメントは data-architecture.md の「Local DB ↔ Remote DB」同期の詳細。

概要

各ブラウザはローカルの RxDB (IndexedDB) を持ち、HTTP pull/push を介して
中央の RxDB (MongoDB) サーバーと同期する。
さしあたり共同同時編集は想定せず、単一ユーザーが一度に一つのデバイスで操作する前提。

戦略: Server Wins

push 時に conflict が検出された場合、サーバーの状態を正とする。
クライアントはサーバー状態を採用して resolve する。

Conflict 検出 (Push)

各 push 行には assumedMasterState(クライアントが想定するサーバーの現在状態)が
付与される。サーバーはこれを実際の状態と比較する:

  • 一致 → 書き込みを受理
  • 不一致 → 書き込みを拒否し、実際のサーバー状態を conflict として返却

削除と softDeleted フィールド

Local DB では doc.remove() を直接呼ばず、removePage() フック経由で
softDeleted: trueupdatedAt を更新する。これにより:

  • 削除済みドキュメントを find({ selector: { softDeleted: true } }) で取得可能
  • RxDB の内部 deleted/deleted$ と競合しないよう softDeleted という名前を使用

Remote DB の pages コレクションに削除済みドキュメントを直接保持する
softDeleted: true で upsert)。tombstones コレクションは廃止。

復活と slug 再利用

  • クライアントが softDeleted: false を push → 受理して upsert
  • 非削除ドキュメントの push 時、slug 一意性は softDeleted: false のドキュメント間でのみチェック

Push バッチの処理順序

同一バッチ内で削除と作成が混在する場合、
softDeleted: true のドキュメントを先に処理する。これにより slug 一意性チェックが
まだ削除されていない旧ページに衝突することを防ぐ。

updatedAt の意味

PageDoc.updatedAt は「DB エントリがいつ書き込まれたか」を表すシステムタイムスタンプ。
ファイルの mtime (fileObj.lastModified) ではなく Date.now() を使用する。
コンテンツの変更日時は content.modified が別途保持する。

Some Rights Reserved. (cc) 2026 Baku Hashimoto
This site is generated by Garden.ooo