章と記事の一覧
動かすストレージ
Durable Object を自分で書く
インメモリ状態と SQLite の違いを、コードを書き換えて確かめる
エディタのコードは App という名前の Durable Object クラスである。実行すると、あなたのクラスがこのサイトの Durable Object の子として起動し、fetch() が呼ばれる。
試すこと
- そのまま何度か実行する。
memoryとsqliteが同じ数だけ増える。 - コメントを 1 文字書き換えて実行する。コードが変わるとインスタンスが作り直され、
memoryは 1 に戻る。sqliteは続きから増える。
memory は退避やコード更新で消えるインメモリ状態、sqlite は ctx.storage.sql に書いた永続状態である。本番では、アクセスが約 10 秒途絶えたときにも memory は同じように消える。
仕組み
このサイトはあなたのクラスを直接 DO として登録しているわけではない。サイト側の DO が「親」になり、ctx.facets.get() であなたのクラスを facet(子)として読み込む。facet は親とは別の SQLite を持ち、あなたのコードは親のデータに触れない。コードを書き換えたときは ctx.facets.abort() で facet を止めて作り直す。ストレージは残るので、sqlite だけが続きから数えられる。
ネットワークは遮断され、CPU は 100ms までに制限される。
import { DurableObject } from "cloudflare:workers";
// App という名前のクラスが、このサイトの Durable Object の子(facet)として動く
// A class named App runs as a child (facet) of this site's Durable Object
export class App extends DurableObject {
// インメモリ状態:最速だが、退避やコード更新で消える
// In-memory state: fastest, but lost on eviction or a code change
memory = 0;
fetch() {
this.memory += 1;
// SQLite:ディスクに残り、コードを書き換えても消えない
// SQLite: durable, survives even a code change
const sql = this.ctx.storage.sql;
sql.exec("CREATE TABLE IF NOT EXISTS hits (n INTEGER)");
sql.exec("INSERT INTO hits VALUES (1)");
const sqlite = sql.exec("SELECT COUNT(*) AS c FROM hits").one().c;
// 数字を書き換えて再実行すると、memory は 1 に戻り、sqlite は増え続ける
// Edit anything and re-run: memory resets to 1, sqlite keeps counting
return Response.json({ memory: this.memory, sqlite });
}
}
実行結果
実行するとここに結果が出ます。ネットワークは塞がれていますが、D1・KV・R2・Durable Object の状態は訪問者全員で共有されます。