コンテンツにスキップ

Offline Mode

すべての plasma アプリは、mutation が IDB から即座に返り、sync ループがバックグラウンドで起こるという意味で offline-first です。しかし plasma には より オフラインにしたいときのための追加のノブが 2 つあります:

  • PlasmaClientOptions.offline: true — ネットワークを完全にスキップします。plasma sync サーバーがまったく存在しない React Native、Tauri、Electron、エアギャップ環境に便利です。
  • TableOptions.changeLogSuppressed: true — table ごとに sync ループをオプトアウトします。ブラウザを決して離れないローカル専用のキャッシュ table です。

これらは自由に組み合わせられます。

offline: true — クライアント全体

Section titled “offline: true — クライアント全体”
const plasma = createPlasmaClient({
schema,
mutators,
dbName: "notes",
endpoint: "/sync", // 依然として必須(ダミー値でよい)
clientGroupID: "user-42",
schemaVersion: "notes-v1",
getContext: async () => ({ userId: "u1" }),
offline: true,
})

設定すると:

  • client.start() はポーリングタイマー / online リスナー / WebSocket サブスクリプションを開きません。
  • client.pushOnce()client.pullOnce() は no-op です(HTTP 呼び出しなしで即座に解決します)。
  • blob アップロードは実行されません。client.readFile(ref)_plasma_blobs_local からのみ提供します; 本来なら blob を localready に遷移させるアップロードは local のままです。
  • outbox は依然として蓄積します。 mutation は通常どおりエンキューされます。offline を(クライアントを再構築して)false に戻すと、outbox は通常の push パスを通じてフラッシュします。

オフラインモードでの client.resetLocalState() は throw します:

plasma: resetLocalState() is not supported when PlasmaClientOptions.offline is true — the local state cannot be re-hydrated from the server and the offline outbox would be lost.

オフラインアプリには再ハイドレートするサーバーがありません。ローカル状態を消去すると、戻る手段なしにすべての未フラッシュの mutation を破壊します。本当に必要なら、まずオンラインに切り替え、クライアントを再構築し、そこでリセットしてください。

一部の table はクライアントのみに属します。セッションドラフト、タブごとのキャッシュ、リロードを生き延びるべきだがサーバーには決して sync すべきでない一時的なフィルタ状態です:

const drafts = table("drafts", {
id: id(),
snapshot: text(),
updatedAt: int(),
}, {
changeLogSuppressed: true,
})
const schema = defineSchema({
todos, // synced(デフォルト)
drafts, // ローカル専用
})

サーバー側への効果:

  • ensureSchema / runMigrations は suppressed table の AFTER-write トリガーをスキップします。drafts への生ドライバ書き込みは _plasma_changes 行を生成しません。
  • pull レスポンスは suppressed table の変更を決して含みません。

クライアント側への効果:

  • rebuildOptimistic はユーザー可視ストアをクリアするとき suppressed table をスキップします。ローカル専用の行は pull をまたいで保持されます。
  • runMutate は mutator がどの table を触ったかを検査します(新しい engine.recordTouchedTables hook 経由)。触ったすべての table が suppressed なら、outbox エントリは完全にスキップされます — その mutation に対して push は決して出ていきません。

offline + changeLogSuppressed の組み合わせ

Section titled “offline + changeLogSuppressed の組み合わせ”

これらは一緒に機能します。Tauri アプリはクライアント全体に offline: true を使い、いくつかの table には「内部の change log ですら不要な帳簿付け」として changeLogSuppressed: true を使うかもしれません:

  • すべての書き込みはローカル IDB 書き込みです。
  • 非 suppressed table は依然として _plasma_changes トリガーを埋めます(後でオンラインに切り替えたくなった場合のため)。
  • suppressed table はトリガーもスキップします — 純粋なローカル状態です。

PlasmaClientOptions.offline構築時 のフラグです。v1.0 には client.setOffline(true) のランタイムトグルはありません。

アプリをオフラインからオンラインに遷移させるには:

  1. オフライン outbox が保持している未フラッシュの状態を保存します(通常は何もありません — plasma がフラッシュしてくれます)。
  2. offline: false でクライアントを再構築します。
  3. client.start() を呼びます。

IDB ストア(base + user ストア + outbox)は dbName でキーが付くため、再構築をまたいで共有されます。オフライン実行のすべての outbox エントリは、最初の push でフラッシュされます。

オフライン vs オンラインの検出

Section titled “オフライン vs オンラインの検出”

クライアントは fetch が失敗すると kind: "network"SyncClientError イベントを発火します。実際には onError を追加してサブスクライブできます:

createPlasmaClient({
...,
onError: (err) => {
if (err.kind === "network") {
setBanner("offline")
}
},
})
// 次の成功した push/pull でバナーをリセット:

組み込みの「今オンライン」イベントはありません — plasma は透過的にリトライします。ブラウザレベルのオンライン/オフライン遷移に反応する必要があれば navigator.onLine を使ってください。