Cloudflare QueuesのプロデューサーをSvelteKitで実装した話
Cloudflare Queuesを使うと、処理を非同期でバックグラウンド実行できます。重い処理をQueueに投げることで、ユーザーを待たせずにレスポンスを返せます。
Cloudflare Queuesとは
ユーザー → フォーム送信 → Queueにメッセージを積む → すぐレスポンスを返す
↓
(別で)Consumerがメッセージを処理
| 役割 | 内容 |
|---|---|
| プロデューサー | メッセージをQueueに送る側 |
| コンシューマー | Queueからメッセージを受け取って処理する側 |
セットアップ
1. Queueを作成
npx wrangler queues create sveltekit-blog-queue
--local オプションなしで実行すると、Cloudflare上にQueueが作成されます。D1やKVと違いローカル専用の作成はできません。
2. wrangler.jsonc にプロデューサーバインディングを追加
"queues": {
"producers": [
{
"binding": "MY_QUEUE",
"queue": "sveltekit-blog-queue"
}
]
}
3. src/app.d.ts に型を追加
interface Platform {
env: {
MY_QUEUE: Queue; // ← 追加
// ... 他のenv
};
}
プロデューサーの実装
src/routes/queue-demo/+page.server.ts
import type { Actions } from './$types';
export const actions: Actions = {
send: async ({ request, platform }) => {
const data = await request.formData();
const message = data.get('message') as string;
await platform!.env.MY_QUEUE.send({
message,
sentAt: new Date().toISOString()
});
return { queued: true };
},
};
src/routes/queue-demo/+page.svelte
<script lang="ts">
import { enhance } from '$app/forms';
let { form } = $props();
</script>
<h1>Queue デモ</h1>
<form method="POST" action="?/send" use:enhance>
<input type="text" name="message" placeholder="メッセージを入力" />
<button type="submit">Queueに送る</button>
</form>
{#if form?.queued}
<p style="color: green">Queueに追加しました!</p>
{/if}
コンシューマーについて
SvelteKit + adapter-cloudflare の構成でコンシューマーを実装するには、ビルド後に生成されるWorkerファイルにqueueハンドラを追加する必要があり、非trivialな対応が必要です。
実務ではコンシューマー専用の別Workerを用意する構成が一般的です。
SvelteKit Worker(プロデューサー)→ Queue → 別のWorker(コンシューマー)
コンシューマーなし時の挙動
コンシューマーが設定されていない場合、メッセージは:
- Queueに追加される
- コンシューマーがいないので処理できない
- 最大3回リトライされる
- 3回失敗後に自動で破棄される
Cloudflareダッシュボードのキューのステータスが「非アクティブ」になるのは、コンシューマーが設定されていないためで、プロデューサーの動作には影響しません。
Cloudflareダッシュボードで確認
dash.cloudflare.com → Queues → キュー名 でメッセージの送受信数を確認できます。
| ステータス | 意味 |
|---|---|
| アクティブ | コンシューマーが設定されていてメッセージを処理できる |
| 非アクティブ | コンシューマーが設定されていない |
まとめ
- Queuesはローカル専用の作成はできない(Cloudflareに実際に作成される)
- プロデューサー側は
platform.env.MY_QUEUE.send(メッセージ)で送信できる - コンシューマーなしの場合、メッセージは3回リトライ後に破棄される
- SvelteKit + adapter-cloudflareでのコンシューマー実装は複雑なため、実務では別Workerを用意するのが一般的