durable-objects について
Cloudflare Durable Objectsによるエッジ上の状態管理と調整を実装・レビューする開発者向けのコーディングスキルです。最新ドキュメントの参照を重視し、ストレージ、並行処理、設定、テストの指針を扱います。
主な機能
- 01状態管理と調整の実装ガイド
- 02RPC、アラーム、WebSocket
- 03Wranglerのバインディングとマイグレーション
- 04SQLiteストレージと並行処理の規則
- 05Cloudflare Vitestのテストガイド
活用シーン
- 01チャットルームやマルチプレイヤー調整の実装
- 02Durable Objectコードのレビュー
- 03バインディングとマイグレーションの設定
- 04Durable Objectのテスト作成
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ cloudflare/ skills --skill durable-objectsインストール後、Claude Code で/durable-objectsを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/rules.mdtesting.mdworkers.md詳細
Durable Objects
Durable Objects を使用して、Cloudflare のエッジ上に状態を保持し、連携するアプリケーションを構築します。
情報の取得元
Durable Objects の API や設定に関する知識は古くなっている可能性があります。Durable Objects に関する作業では、事前学習済みの知識よりも情報の取得を優先してください。
機能を実装するときは、該当するドキュメントページを取得してください。
使用する場面
- 状態を保持して連携する新しい Durable Object クラスの作成
- RPC メソッド、アラーム、WebSocket ハンドラーの実装
- ベストプラクティスに照らした既存の DO コードのレビュー
- DO バインディングとマイグレーション用の wrangler.jsonc/toml の設定
- Cloudflare の Vitest 統合を使用したテストの作成
- シャーディング戦略と親子関係の設計
リファレンスドキュメント
./references/rules.md- 基本ルール、ストレージ、並行処理、RPC、アラーム- テストのリファレンス - 最新の Vitest ドキュメント、マイグレーションの選択肢、テストの選び方
./references/workers.md- Workers のハンドラー、型、wrangler 設定、可観測性
検索対象:blockConcurrencyWhile、idFromName、getByName、setAlarm、sql.exec
基本原則
Durable Objects を使用する場面
| ニーズ | 例 |
|---|---|
| 連携 | チャットルーム、マルチプレイヤーゲーム、共同編集ドキュメント |
| 強い一貫性 | 在庫、予約システム、ターン制ゲーム |
| エンティティごとのストレージ | マルチテナント SaaS、ユーザーごとのデータ |
| 永続的な接続 | WebSocket、リアルタイム通知 |
| エンティティごとのスケジュール実行 | サブスクリプションの更新、ゲームのタイムアウト |
使用しない場面
- ステートレスなリクエスト処理(通常の Workers を使用してください)
- グローバルに最大限の分散が必要な場合
- 独立したリクエストを大量にファンアウトする場合
クイックリファレンス
Wrangler の設定
// wrangler.jsonc
{
"durable_objects": {
"bindings": [{ "name": "MY_DO", "class_name": "MyDurableObject" }]
},
"migrations": [{ "tag": "v1", "new_sqlite_classes": ["MyDurableObject"] }]
}
基本的な Durable Object パターン
import { DurableObject } from "cloudflare:workers";
export interface Env {
MY_DO: DurableObjectNamespace<MyDurableObject>;
}
export class MyDurableObject extends DurableObject<Env> {
constructor(ctx: DurableObjectState, env: Env) {
super(ctx, env);
ctx.blockConcurrencyWhile(async () => {
this.ctx.storage.sql.exec(`
CREATE TABLE IF NOT EXISTS items (
id INTEGER PRIMARY KEY AUTOINCREMENT,
data TEXT NOT NULL
)
`);
});
}
async addItem(data: string): Promise<number> {
const result = this.ctx.storage.sql.exec<{ id: number }>(
"INSERT INTO items (data) VALUES (?) RETURNING id",
data
);
return result.one().id;
}
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const stub = env.MY_DO.getByName("my-instance");
const id = await stub.addItem("hello");
return Response.json({ id });
},
};
重要なルール
- 連携の単位を軸にモデル化する - 1 つのグローバル DO ではなく、チャットルーム、ゲーム、ユーザーごとに DO を 1 つ作成します
- 決定的なルーティングには
getByName()を使用する - 同じ入力は同じ DO インスタンスにルーティングされます - SQLite ストレージを使用する - マイグレーションで
new_sqlite_classesを設定します - コンストラクターで初期化する - スキーマのセットアップにのみ
blockConcurrencyWhile()を使用します - RPC メソッドを使用する - fetch() ハンドラーは使用しません(互換性日付 >= 2024-04-03)
- まず永続化し、その後キャッシュする - インメモリ状態を更新する前に、必ずストレージに書き込みます
- DO ごとにアラームは 1 つ -
setAlarm()は既存のアラームを置き換えます
認可
Durable Objects に個別のロールや権限はありません。アクセス権は、それらを実装する Worker に従います。可観測性や Data Studio へのアクセス権を付与する前に、最新の Durable Objects の認可ガイダンスを取得し、Workers のロールを対象の Worker または Workers 製品に限定してください。
アンチパターン(絶対に避けること)
- すべてのリクエストを処理する単一のグローバル DO(ボトルネックになります)
- リクエストのたびに
blockConcurrencyWhile()を使用する(スループットが大幅に低下します) - 重要な状態をメモリ内だけに保存する(エビクションやクラッシュ時に失われます)
- 関連するストレージ書き込みの間に
awaitを使用する(アトミック性が損なわれます) fetch()や外部 I/O の間、blockConcurrencyWhile()を保持する
スタブの作成
// Deterministic - preferred for most cases
const stub = env.MY_DO.getByName("room-123");
// From existing ID string
const id = env.MY_DO.idFromString(storedIdString);
const stub = env.MY_DO.get(id);
// New unique ID - store mapping externally
const id = env.MY_DO.newUniqueId();
const stub = env.MY_DO.get(id);
ストレージ操作
// SQL (synchronous, recommended)
this.ctx.storage.sql.exec("INSERT INTO t (c) VALUES (?)", value);
const rows = this.ctx.storage.sql.exec<Row>("SELECT * FROM t").toArray();
// KV (async)
await this.ctx.storage.put("key", value);
const val = await this.ctx.storage.get<Type>("key");
アラーム
// Schedule (replaces existing)
await this.ctx.storage.setAlarm(Date.now() + 60_000);
// Handler
async alarm(): Promise<void> {
// Process scheduled work
// Optionally reschedule: await this.ctx.storage.setAlarm(...)
}
// Cancel
await this.ctx.storage.deleteAlarm();
テスト
テストスイートを設定したり Durable Object のテストを作成したりする前に、テストのリファレンスをお読みください。最新のセットアップ方法、API、例に加え、テスト対象にすべき動作を確認できます。