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(コンシューマー)

コンシューマーなし時の挙動

コンシューマーが設定されていない場合、メッセージは:

  1. Queueに追加される
  2. コンシューマーがいないので処理できない
  3. 最大3回リトライされる
  4. 3回失敗後に自動で破棄される

Cloudflareダッシュボードのキューのステータスが「非アクティブ」になるのは、コンシューマーが設定されていないためで、プロデューサーの動作には影響しません。


Cloudflareダッシュボードで確認

dash.cloudflare.comQueues → キュー名 でメッセージの送受信数を確認できます。

ステータス 意味
アクティブ コンシューマーが設定されていてメッセージを処理できる
非アクティブ コンシューマーが設定されていない

まとめ

  • Queuesはローカル専用の作成はできない(Cloudflareに実際に作成される)
  • プロデューサー側は platform.env.MY_QUEUE.send(メッセージ) で送信できる
  • コンシューマーなしの場合、メッセージは3回リトライ後に破棄される
  • SvelteKit + adapter-cloudflareでのコンシューマー実装は複雑なため、実務では別Workerを用意するのが一般的
← トップページに戻る