Cloudflare Durable Objects
Cloudflare Durable Objects は HTTP リクエストを直接処理できません。代わりに、次の 2 段階の仕組みで動作します。
- Worker がクライアントからの HTTP fetch リクエストを受け取ります
- Worker が Durable Object に RPC(リモートプロシージャコール)を行います
- Durable Object が RPC を処理し、結果を Worker に返します
- Worker が HTTP レスポンスをクライアントに返します
Cloudflare Worker で Hono をルーターとして使い、RPC(リモートプロシージャコール)を通じて Durable Objects とやり取りできます。Cloudflare Workers の互換性日付 2024-04-03 以降では、この方法が推奨されています。
例:カウンターの Durable Object
ts
import { DurableObject } from 'cloudflare:workers'
import { Hono } from 'hono'
export class Counter extends DurableObject {
// In-memory state
value = 0
constructor(ctx: DurableObjectState, env: unknown) {
super(ctx, env)
// `blockConcurrencyWhile()` ensures no requests are delivered until initialization completes.
ctx.blockConcurrencyWhile(async () => {
// After initialization, future reads do not need to access storage.
this.value = (await ctx.storage.get('value')) || 0
})
}
async getCounterValue() {
return this.value
}
async increment(amount = 1): Promise<number> {
this.value += amount
await this.ctx.storage.put('value', this.value)
return this.value
}
async decrement(amount = 1): Promise<number> {
this.value -= amount
await this.ctx.storage.put('value', this.value)
return this.value
}
}
// Create a new Hono app to handle incoming HTTP requests
type Bindings = {
COUNTER: DurableObjectNamespace<Counter>
}
const app = new Hono<{ Bindings: Bindings }>()
// Add routes to interact with the Durable Object
app.get('/counter', async (c) => {
const env = c.env
const id = env.COUNTER.idFromName('counter')
const stub = env.COUNTER.get(id)
const counterValue = await stub.getCounterValue()
return c.text(counterValue.toString())
})
app.post('/counter/increment', async (c) => {
const env = c.env
const id = env.COUNTER.idFromName('counter')
const stub = env.COUNTER.get(id)
const value = await stub.increment()
return c.text(value.toString())
})
app.post('/counter/decrement', async (c) => {
const env = c.env
const id = env.COUNTER.idFromName('counter')
const stub = env.COUNTER.get(id)
const value = await stub.decrement()
return c.text(value.toString())
})
// Export the Hono app as the Worker's fetch handler
export default appwrangler.jsonc:
jsonc
{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "durable",
"main": "src/index.ts",
"compatibility_date": "2025-04-14",
"migrations": [
{
"new_sqlite_classes": ["Counter"],
"tag": "v1",
},
],
"durable_objects": {
"bindings": [
{
"class_name": "Counter",
"name": "COUNTER",
},
],
},
"observability": {
"enabled": true,
},
}これで、Durable Object と連携する Hono アプリケーションが完成しました。Hono ルーターは、Durable Object のメソッドを呼び出して公開するための、わかりやすい API インターフェースを提供します。