コンテンツにスキップ

plasma

一つの schema と一つの mutator セットが、ブラウザと Cloudflare Workers の両方で同じように動く。sync / live query / ファイル / CRDT 収束は全部 engine が面倒を見ます。

plasma は Cloudflare Workers + D1 スタックに組み込む TypeScript の sync engine です。schema と mutation 関数を 一度だけ 定義すると、 それが:

  • ブラウザ側で IndexedDB に対して optimistic に走る — 即座にリアクティブな UI
  • Worker 側で D1 (もしくは Hyperdrive 経由の Postgres) に対して canonical に走る — source of truth

plasma は /sync/* エンドポイント、change log、pull cookie、outbox、 rebase、WebSocket poke、file() column 用の R2 blob upload まで、 その間にある全部を面倒見ます。

同型 (Isomorphic) な DSL

型がエンドツーエンドに流れます。db.select().from(todos).where(eq(todos.done, 0)) はブラウザでも Worker でも同じ意味で、同じ形の row を返します。

Optimistic + convergent

Mutation は呼び出した瞬間ローカルに適用されます。sync ループが それをサーバーへ push し、並行変更の上に rebase し、 CRDT column を使えば衝突解決のボイラープレート無しで収束します。

ファイル / 暗号化 / CRDT

file() column を宣言すれば R2 がバイトを扱います。.encrypted() を 付ければクライアントが at-rest で包みます。crdtOrSet<string>() を 宣言すれば、複数タブが同時に追加・削除しても losslessly マージされます。

Cloudflare ネイティブ

SyncCoordinator (hibernation 対応 WebSocket ファンアウトの Durable Object)、 SequencerDO (リージョンごとの単調 ID 生成)、Miniflare + workerd テスト用 ハーネス、R2 blob ストレージアダプター — 全部同梱。

plasma は「ユーザーがそれぞれ管理可能な行のセットを所有・少人数で共有する」形の アプリ向けに設計されています: todo / notes / チャット / kanban / 下書き / 連絡先 / 小規模な共同編集ドキュメント。

一方、public timeline (Twitter 型) や analytics 中心のワークロードには 向いていません。change log は書き込みで増えて読み込みでは増えないので、 「読み込み多め・書き込み少なめ」は問題ありません。ですが「1 行を数千人の subscriber にファンアウトする」形は対象外です。