コンテンツにスキップ

第6章: 定期実行バッチ(Cron)と非同期処理(実践チュートリアル)

個人開発で「毎朝9時に最新データを収集して通知したい」「定期的に古いレコードをバッチ削除したい」という要件は頻出します。VPSやEC2を24時間起動し続けると月数百円〜数千円の固定費がかかりますが、Cloudflare Workersの Cron Triggers を使えば 完全無料(無料枠内) でサーバーレスバッチを運用できます。


本チュートリアルのゴール

  1. Cron Triggers:
    • wrangler.jsonc でのスケジュール構文(毎時・日次実行)
    • 定期実行ハンドラー(scheduled)の実装
    • 待たずにテストできるローカル curl トリガー術
  2. Cloudflare Queues:
    • キューの作成とプロデューサー/コンシューマー設定
    • 重いAPI呼び出しや通知処理の非同期平滑化

Part 1: Cron Triggers(定期バッチ)ハンズオン

Step 1: プロジェクト設定(wrangler.jsonc

Workersにスケジュール設定を追加します。

{
"name": "my-cron-batch",
"main": "src/index.ts",
"compatibility_date": "2024-09-01",
"triggers": {
"crons": [
// 1. 毎朝9時(JST = UTC 00:00)に実行
"0 0 * * *",
// 2. 毎時0分に実行
"0 * * * *"
]
}
}

[!NOTE] Cronの時刻は「UTC(協定世界時)」
日本時間(JST)は UTC+9 です。朝9時(JST)に実行したい場合は 0 0 * * *(UTC 0時)と記述します。


Step 2: バッチ処理ハンドラーの実装

src/index.tsscheduled イベントリスナーを記述します。

export default {
// 1. 定期実行ハンドラー(Cronが発火した際に呼び出される)
async scheduled(event: ScheduledEvent, env: Env, ctx: ExecutionContext) {
const triggerTime = new Date(event.scheduledTime).toISOString();
console.log(`[CRON START] トリガー時刻: ${triggerTime}, cron式: ${event.cron}`);
// 例: 外部APIから為替レートを取得してDiscord/Slackに通知する処理
try {
const res = await fetch('https://open.er-api.com/v6/latest/USD');
const data: any = await res.json();
const jpyRate = data?.rates?.JPY;
console.log(`現在のUSD/JPYレート: ${jpyRate}`);
// 重い処理や外部通知は ctx.waitUntil で安全に待機
ctx.waitUntil(
sendNotification(`【定期為替バッチ】現在のUSD/JPY: ${jpyRate} 円 (UTC: ${triggerTime})`)
);
} catch (error) {
console.error('[CRON ERROR] バッチ処理失敗:', error);
}
},
// 2. HTTPエンドポイント(手動トリガーやヘルスチェック用)
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
return new Response(JSON.stringify({ status: 'Batch Worker is running' }), {
headers: { 'Content-Type': 'application/json' },
});
}
};
async function sendNotification(message: string) {
// Webhook送信ロジック(Slack / Discord / LINE)
console.log('[NOTIFICATION]', message);
}

Step 3: ローカル環境での即時テスト検証

Cronのテストで「次の時間まで何時間も待つ」必要はありません。wrangler dev 起動中に特別なテストエンドポイントへリクエストを送ることで、即座に発火させられます。

Terminal window
# ローカルサーバー起動
npx wrangler dev

別のターミナルから以下の curl を実行します。

Terminal window
# 登録したCron式を指定して強制トリガー
curl "http://localhost:8787/__scheduled?cron=0+0+*+*+*"

開発サーバーのターミナル出力:

[CRON START] トリガー時刻: 2026-09-21T00:00:00.000Z, cron式: 0 0 * * *
現在のUSD/JPYレート: 148.5
[NOTIFICATION] 【定期為替バッチ】現在のUSD/JPY: 148.5 円

わずか1秒でバッチ処理の正常動作を確認できます。


Step 4: 本番デプロイ

Terminal window
npx wrangler deploy

デプロイ後、Cloudflareダッシュボードの Workers > 対象Worker > Triggers タブでも登録されたCronスケジュールが有効化されていることを確認できます。


Part 2: Cloudflare Queues(非同期キューイング)

リクエスト急増時のサーバーダウンを防ぎ、処理を順次実行したい場合に Queues を使用します。

1. キューの作成(CLI)

Terminal window
npx wrangler queues create email-notification-queue

2. wrangler.jsonc でのキュー紐付け

{
"name": "my-queue-worker",
"main": "src/index.ts",
// メッセージを送信する側(Producer)
"queues": {
"producers": [
{ "binding": "EMAIL_QUEUE", "queue": "email-notification-queue" }
],
// メッセージを受信・処理する側(Consumer)
"consumers": [
{ "queue": "email-notification-queue", "max_batch_size": 10, "max_batch_timeout": 5 }
]
}
}

3. メッセージ送信と受信の実装例

export default {
// HTTPリクエストを受けたらキューに投げて即レスポンス
async fetch(req: Request, env: Env): Promise<Response> {
const payload = await req.json();
await env.EMAIL_QUEUE.send(payload); // キューへエンキュー
return new Response('Queued successfully', { status: 202 });
},
// キューからバッチでメッセージを取り出して処理
async queue(batch: MessageBatch<any>, env: Env): Promise<void> {
for (const message of batch.messages) {
console.log('キュー受信:', message.body);
// メール送信処理など
message.ack(); // 正常完了通知
}
}
};

まとめ

  • Cron Triggers: 常駐サーバーゼロで定時ジョブを動かし、__scheduled エンドポイントで爆速ローカル検証。
  • Queues: 大量アクセスをキューに溜めて安全に分散処理。

次章(第7章)では、オープンソースLLM(Llama 3等)をWorkersから呼び出す Workers AI のハンズオンに進みます。


💡 用語解説コラム

[!NOTE] Cron式 (Cron Expression)
定期実行のスケジュールを「分 時 日 月 曜日」の5つのフィールドで表現する構文。CloudflareではUTC(協定世界時)を基準に判定されるため、日本時間(JST)から9時間引いて計算します。

[!NOTE] メッセージキュー (Message Queue)
リクエストを一時的に待ち行列に保存し、バックグラウンドで順番に処理する仕組み。瞬間的なアクセス集中によるサーバーダウンを防ぐ「リクエストの平滑化」に効果的です。