Migrations
plasma の schema 変更は deploy 前に生成します。Worker runtime は request path で table を作ったり照合したりしません。CLI で生成・レビュー・適用した artifact に対して sync traffic を処理します。
6 つの command があります:
| Command | 目的 |
|---|---|
plasma generate |
次の SQL migration / snapshot / journal / manifest / schema version を生成する。 |
plasma generate --check |
artifact を再生成し、commit 済み artifact と byte-for-byte 比較する。 |
plasma generate --watch |
schema.ts を監視し、変更ごとに子 process で generate する。 |
plasma migrate deploy |
未適用 SQL artifact を crash-safe lock と tracking table 付きで適用する。 |
plasma migrate status |
適用済み row、現在の lock、artifact と DB の差分を表示する。 |
plasma migrate baseline |
既存 DB を drift check 後に 0000_baseline として採用する。 |
import { defineConfig } from "@sh1n4ps/plasma-cli/config"
export default defineConfig({ schema: "./src/shared/schema.ts", out: "./plasma", localDbPath: "./local.sqlite", d1: { accountId: process.env.CLOUDFLARE_ACCOUNT_ID, databaseId: process.env.CLOUDFLARE_D1_DATABASE_ID, apiToken: process.env.CLOUDFLARE_API_TOKEN, },})import { defineMutators, defineSchema, id, table, text } from "@sh1n4ps/plasma-core"
export const todos = table("todos", { id: id(), title: text() })export const schema = defineSchema({ todos })export const mutators = defineMutators<typeof schema, { userId: string }>()({})初回生成:
plasma generate --name baseline生成される構成:
plasma/ migrations/ 0000_baseline.sql meta/ 0000_snapshot.json _journal.json _manifest.json schema-version.tsこの directory 全体を commit します。生成された schema-version.ts が client と Worker の両方で使う SCHEMA_VERSION を export します。手動編集や手動 bump はしません。
Command 例
Section titled “Command 例”plasma generate
Section titled “plasma generate”plasma generate --schema ./src/shared/schema.ts --out ./plasma --name add-priority初回 schema では baseline SQL を出します。2 回目以降は plasma/meta/_journal.json から最新 snapshot を読み、宣言 schema と mutator manifest から新 snapshot を構築し、diff / unsafe validation / size estimate を通したうえで artifact directory を atomic に差し替えます。
plasma generate --check
Section titled “plasma generate --check”plasma generate --check --schema ./src/shared/schema.ts --out ./plasmaCI 用です。静的 validation と artifact drift 検出だけを行い、D1 credential は不要です。exit code は stable で、0 は一致、1 は validation/error、2 は drift です。
--check --probe は D1 に接続して batch limit を実測したい環境向けの opt-in です。
plasma generate --watch
Section titled “plasma generate --watch”plasma generate --watchwatch mode は各 generate を子 process で実行するため、前回の schema import による TypeScript module cache が次回に漏れません。
plasma migrate deploy
Section titled “plasma migrate deploy”# local smoke testplasma migrate deploy --local --local-db ./local.sqlite
# production D1 REST APIplasma migrate deploy --wait 30deploy は _plasma_migrations と _plasma_migrations_lock を bootstrap し、lease を取得し、SQL batch の前に running row を記録します。その後 SQL と完了 update を別 batch で適用し、verifier がある場合は検証して、lease を解放します。失敗や crash は tracking table に残ります。
plasma migrate status
Section titled “plasma migrate status”plasma migrate status --local --local-db ./local.sqliteplasma migrate status --jsonstatus は artifact journal と _plasma_migrations を比較し、現在の lock holder を表示します。JSON output は常に次の envelope です:
{ "version": "1", "exitCode": 0, "results": {}, "warnings": [], "errors": [] }plasma migrate baseline
Section titled “plasma migrate baseline”plasma migrate baseline --local --local-db ./existing.sqliteplasma migrate baseline --forcebaseline は既存 DB を introspect し、宣言 schema と比較して、drift があれば --force なしでは拒否します。0000_baseline.sql / snapshot / journal / manifest と、将来の deploy が baseline 適用済みと判断できる self-recording _plasma_migrations insert を生成します。
unsafe と判定される変更
Section titled “unsafe と判定される変更”生成は、データ損失、IndexedDB semantic の破壊、sync protocol の曖昧化につながる変更を拒否します。table / column drop、kind 変更、nullable から NOT NULL、unique 追加、mutator 必須 arg 追加、mutator manifest 未宣言、暗号化 key 変更、ref().onDelete semantic 変更が対象です。--force は、別途データ移行済みの場合に限って使い、refuse を warning に降格します。
crash-safe apply の仕組み
Section titled “crash-safe apply の仕組み”D1 は送信済み batch を abort できないため、deploy runner は 2 batch model です:
- tracking / lock table を毎回 bootstrap。
_plasma_migrations_lockを compare-and-swap lease で取得。- migration SQL batch の外で
runningrow を insert。 - migration statements と
appliedupdate を 1 batch で適用。 - post-apply verification 後に
verifiedまたはverified_mismatchへ更新。 - 次回起動時、古い
runningrow はfailedにする。--forceなら idempotent retry を試みる。
heartbeat が lock loss を検出したら次の migration は発行しません。ただし in-flight D1 batch は完了を待つため、2 つの runner が同時に進む状態を避けます。
hash breakdown と handshake
Section titled “hash breakdown と handshake”各 snapshot は shape / mutators / auth / protocol / conflict の 5 つの独立 SHA-256 hash を持ちます。その JCS canonical composite hash の先頭 16 hex が SCHEMA_VERSION です。journal には内訳も保存されるため、drift report はどの次元が変わったかを示せます。
server は minClientVersion を設定できます。新規 project は、generated schema version、"keep" mismatch handling、hash breakdown、IDB migration diagnostics を理解する最初の client line として、少なくとも 1.0.0 を要求することを推奨します。
client IDB migration の 4 分岐
Section titled “client IDB migration の 4 分岐”pull した schema version が local IndexedDB metadata と違う場合、client は次の 4 分岐で判断します:
| 分岐 | 結果 |
|---|---|
| outbox 空 + local cache 互換 | metadata を migrate して続行。 |
| outbox 空 + local cache 非互換 | local state を自動 reset。 |
pending outbox + app が "reset" を返す |
local state を捨て server truth から再開。 |
pending outbox + app が "keep" を返す |
IDB を保持し、user action required として mismatch を表面化。 |
createPlasmaClient({ schema, mutators, endpoint: "/sync", schemaVersion: SCHEMA_VERSION, onSchemaMismatch: async (info) => { if (info.outboxCount === 0) return "reset" return "keep" },})troubleshooting
Section titled “troubleshooting”plasma artifacts are missing—plasma generateを実行し、plasma/directory を commit します。generated artifacts differ from committed artifacts—plasma generateを実行し、SQL / snapshot diff を review して commit します。migration generation refused— JSON のerrors[].detailsを確認し、schema を additive にするか、手動 data migration 後に--forceを使います。previous migration deploy crashed—_plasma_migrations.logsを確認し、SQL が idempotent と判断できる場合のみ--forceで再実行します。- D1 credentials required —
generate --checkは credential 不要です。migrate deployは--localでない限り必要です。