mcpField
C
cloudflare-cron-triggers

cloudflare-cron-triggers

github.com/secondskyクラウド・DevOps240226 回インストール5 週間前に更新
リポジトリ

cloudflare-cron-triggers について

Cloudflare Workers 開発者向けの Cron Triggers スキルです。スケジュール実行ハンドラーの実装、設定、テスト、デプロイを案内し、Cron 式や連携パターン、トラブルシューティングを扱います。

主な機能

  1. 01スケジュール実行ハンドラーの実装ガイド
  2. 025フィールド Cron 式リファレンス
  3. 03Wrangler のトリガー設定
  4. 04ローカルテストとデプロイのガイド
  5. 05複数スケジュールと連携パターン
  6. 06一般的なエラーのトラブルシューティング

活用シーン

  1. 01データベースのクリーンアップを定期実行
  2. 02レポートの定期生成
  3. 03複数のスケジュールによるタスク振り分け
  4. 04スケジュール実行ハンドラーのローカル検証

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/secondsky/claude-skills --skill cloudflare-cron-triggers

インストール後、Claude Code で/cloudflare-cron-triggersを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
common-patterns.md
cron-expressions-reference.md
integration-patterns.md
testing-guide.md
wrangler-config.md
templates/
basic-scheduled.ts
hono-with-scheduled.ts
multiple-crons.ts
scheduled-with-bindings.ts
wrangler-cron-config.jsonc

詳細

Cloudflare Cron Triggers

ステータス:本番環境で利用可能 ✅ 最終更新日:2025-11-25 依存関係:cloudflare-worker-base(Worker のセットアップ用) 最新バージョン:[email protected]、@cloudflare/[email protected]


クイックスタート(5 分)

1. Worker にスケジュールハンドラーを追加する

src/index.ts:

export default {
  async scheduled(
    controller: ScheduledController,
    env: Env,
    ctx: ExecutionContext
  ): Promise<void> {
    console.log('Cron job executed at:', new Date(controller.scheduledTime));
    console.log('Triggered by cron:', controller.cron);

    // Your scheduled task logic here
    await doPeriodicTask(env);
  },
};

重要な理由:

  • ハンドラーの名前は必ず scheduled にしてください(scheduledHandler や onScheduled ではありません)
  • default export オブジェクトでエクスポートする必要があります
  • ES モジュール形式を使用する必要があります(Service Worker 形式ではありません)
2. Wrangler で Cron Trigger を設定する

wrangler.jsonc:

{
  "name": "my-scheduled-worker",
  "main": "src/index.ts",
  "compatibility_date": "2025-10-23",
  "triggers": {
    "crons": [
      "0 * * * *"  // Every hour at minute 0
    ]
  }
}

重要:

  • Cron 式は 5 つのフィールドを使用します:minute hour day-of-month month day-of-week
  • すべての時刻は UTC のみ です(タイムゾーン変換はありません)
  • 変更が全世界に反映されるまで、最大 15 分かかります
3. ローカルでテストする
# Enable scheduled testing
bunx wrangler dev --test-scheduled

# In another terminal, trigger the scheduled handler
curl "http://localhost:8787/__scheduled?cron=0+*+*+*+*"

# View output in wrangler dev terminal

テストのヒント:

  • /__scheduled エンドポイントは --test-scheduled フラグを指定した場合にのみ利用できます
  • クエリパラメーターに任意の Cron 式を渡せます
  • Python Workers では、代わりに /cdn-cgi/handler/scheduled を使用します
4. デプロイする
npm run deploy
# or
bunx wrangler deploy

デプロイ後:

  • 変更が反映されるまで、最大 15 分かかることがあります
  • ダッシュボードを確認してください:Workers & Pages > [Your Worker] > Cron Triggers
  • 過去の実行履歴は Logs タブで確認できます

リファレンスを読み込むタイミング

ユーザーが次の内容に言及したら、すぐに読み込みます:

  • cron-expressions-reference.md → 「cron 構文」、「スケジュール形式」、「式」、「分 時 日」、「X 分ごと」
  • common-patterns.md → 「例」、「ユースケース」、「パターン」、「実例」、「データベースのクリーンアップ」、「レポートの生成」、「方法」
  • integration-patterns.md → 「実装」、「Hono」、「複数のトリガー」、「バインディング」、「ワークフロー」、「エラー処理」
  • wrangler-config.md → 「設定」、「wrangler.jsonc」、「複数の cron」、「環境固有」、「開発環境 ステージング 本番環境」
  • testing-guide.md → 「テスト」、「ローカル開発」、「__scheduled」、「ユニットテスト」、「curl」、「デバッグ」

次の場合は先回りして読み込みます:

  • 新しいスケジュールタスクを作成する場合 → integration-patterns.md を読み込みます
  • wrangler.jsonc を設定する場合 → wrangler-config.md を読み込みます
  • Cron 式をデバッグする場合 → cron-expressions-reference.md を読み込みます
  • ローカルでテストする場合 → testing-guide.md を読み込みます
  • 例を探している場合 → common-patterns.md を読み込みます

Cron 式の構文

5 フィールド形式
* * * * *
│ │ │ │ │
│ │ │ │ └─── Day of Week (0-6, Sunday=0)
│ │ │ └───── Month (1-12)
│ │ └─────── Day of Month (1-31)
│ └───────── Hour (0-23)
└─────────── Minute (0-59)
特殊文字
文字意味例
*毎* * * * * = 毎分
,リスト0,30 * * * * = 毎時 :00 と :30
-範囲0 9-17 * * * = 午前 9 時から午後 5 時まで毎時
/間隔*/15 * * * * = 15 分ごと
よく使われるパターン
# Every minute
* * * * *

# Every 5 minutes
*/5 * * * *

# Every 15 minutes
*/15 * * * *

# Every hour at minute 0
0 * * * *

# Every hour at minute 30
30 * * * *

# Every 6 hours
0 */6 * * *

# Every day at midnight (00:00 UTC)
0 0 * * *

# Every day at noon (12:00 UTC)
0 12 * * *

# Every day at 3:30am UTC
30 3 * * *

# Every Monday at 9am UTC
0 9 * * 1

# Every weekday at 9am UTC
0 9 * * 1-5

# Every Sunday at midnight UTC
0 0 * * 0

# First day of every month at midnight UTC
0 0 1 * *

# Twice a day (6am and 6pm UTC)
0 6,18 * * *

# Every 30 minutes during business hours (9am-5pm UTC, weekdays)
*/30 9-17 * * 1-5

重要:タイムゾーンは UTC のみ

  • すべての Cron Trigger は UTC 時刻で実行されます
  • タイムゾーン変換は利用できません
  • 現地時刻を手動で UTC に変換してください
  • 例:PST の午前 9 時 = UTC の午後 5 時(DST 期間中は翌日)

ScheduledController インターフェース

interface ScheduledController {
  readonly cron: string;           // The cron expression that triggered this execution
  readonly type: string;           // Always "scheduled"
  readonly scheduledTime: number;  // Unix timestamp (ms) when scheduled
}
プロパティ
controller.cron(string)

この実行をトリガーした Cron 式です。

export default {
  async scheduled(controller: ScheduledController, env: Env): Promise<void> {
    console.log(`Triggered by: ${controller.cron}`);
    // Output: "Triggered by: 0 * * * *"
  },
};

**用途:**複数の Cron スケジュールを区別します(複数の Cron Trigger パターンを参照)。

controller.type(string)

Cron によってトリガーされた実行では、常に "scheduled" を返します。

if (controller.type === 'scheduled') {
  // This is a cron-triggered execution
}
controller.scheduledTime(number)

この実行が予定されていた時刻の Unix タイムスタンプ(エポックからの経過時間、ミリ秒)です。

export default {
  async scheduled(controller: ScheduledController): Promise<void> {
    const scheduledDate = new Date(controller.scheduledTime);
    console.log(`Scheduled for: ${scheduledDate.toISOString()}`);
    // Output: "Scheduled for: 2025-10-23T15:00:00.000Z"
  },
};

**注:**これは実際の実行時刻ではなく、予定時刻です。システム負荷により、実際の実行はわずかに遅れることがあります(通常は 1 秒未満)。


実行コンテキスト

export default {
  async scheduled(
    controller: ScheduledController,
    env: Env,
    ctx: ExecutionContext  // ← Execution context
  ): Promise<void> {
    // Use ctx.waitUntil() for async operations that should complete
    ctx.waitUntil(logToAnalytics(env));
  },
};
ctx.waitUntil(promise: Promise<any>)

ハンドラーの戻り後も非同期処理が完了するまで待機するよう、実行コンテキストを拡張します。

用途:

  • 外部サービスへのログ記録
  • アナリティクスのトラッキング
  • クリーンアップ処理
  • 重要度の低いバックグラウンドタスク
export default {
  async scheduled(controller: ScheduledController, env: Env, ctx: ExecutionContext): Promise<void> {
    // Critical task - must complete before handler exits
    await processData(env);

    // Non-critical tasks - can complete in background
    ctx.waitUntil(sendMetrics(env));
    ctx.waitUntil(cleanupOldData(env));
    ctx.waitUntil(notifySlack({ message: 'Cron completed' }));
  },
};

**重要:**失敗した最初の waitUntil() が、ダッシュボードのログにステータスとして報告されます。


統合パターン

本番環境ですぐに使える6つのCronパターン:

  1. Cronを使用したスタンドアロンワーカー - バックグラウンドタスク(データベースのクリーンアップ、レポートの生成)用の単一のスケジュール関数
  2. HonoとCronの組み合わせ - 1つのWorkerでHTTPエンドポイントとスケジュールタスクを実行し、バインディングを共有してコストを削減します
  3. 複数のCronトリガー - controller.cron を使って実行を振り分け、タスクごとに異なるスケジュールを設定します
  4. バインディングへのアクセス - スケジュール関数でD1、KV、R2、AI、Vectorize、Queues、Workflows、Durable Objectsを使用します
  5. Workflowsとの統合 - 複雑で長時間にわたる複数ステップのワークフローをスケジュールに従ってトリガーします
  6. エラーハンドリングのベストプラクティス - 再試行ロジック、アラート(Slack/メール)、失敗ログの記録、モニタリングを備えた包括的なエラーハンドリングを行います

完全な実装例、コードサンプル、設定の詳細、ベストプラクティスについては、references/integration-patterns.md を読み込んでください。


Wranglerの設定

triggers.crons 配列にCronトリガーを追加します。各トリガーには cron 式が必要です。複数のCron(Freeプランでは最大3つ、有料プランでは上限が高くなります)と、dev/staging/productionのデプロイ向けの環境別設定に対応しています。

複数のトリガー、環境別のスケジュール、タイムゾーンの処理、削除手順を含む完全な設定例については、references/wrangler-config.md を読み込んでください。


テストと開発

bunx wrangler dev --test-scheduled を実行して /__scheduled エンドポイントを使い、スケジュール関数をローカルでテストします。その後、curl "http://localhost:8787/__scheduled?cron=0+*+*+*+*" を実行してハンドラーをトリガーします(Cron式ではスペースの代わりに + を使用してください)。

完全なテスト戦略、ローカル開発環境のセットアップ、単体テストの例、統合テストのパターン、本番環境のモニタリング手法については、references/testing-guide.md を読み込んでください。


Green Compute

再生可能エネルギーで稼働するデータセンターでのみCronトリガーを実行します。

Green Computeを有効にする

ダッシュボードから:

  1. Workers & Pagesに移動します
  2. Account details セクションで、Compute Setting を見つけます
  3. Change をクリックします
  4. Green Compute を選択します
  5. Confirm をクリックします

適用対象:

  • アカウント内のすべてのCronトリガー
  • 炭素排出量を削減します
  • 追加料金はかかりません
  • 一部のリージョンでは若干の遅延が生じる場合があります

仕組み:

  • CloudflareがCronの実行を再生可能エネルギーで稼働するデータセンターにルーティングします
  • 風力、太陽光、水力発電などの再生可能エネルギーを使用します
  • 電力購入契約(PPA)と再生可能エネルギー証書(REC)を通じて検証されます

既知の問題の防止

このスキルは、文書化されている6件の問題を防ぎます。

問題#1:Cronの変更が反映されない

エラー: wrangler.jsoncでCronトリガーを更新しても実行されない

ソース: Cloudflare Docs - Cron Triggers

発生する理由:

  • Cronトリガーの変更がグローバルに反映されるまで、最大15分かかります
  • Cloudflareネットワークがエッジノードを更新するには時間が必要です
  • 通常のデプロイのように即時には反映されません

防止策:

  • デプロイ後、実行を確認するまで15分待ちます
  • ダッシュボードで確認します:Workers & Pages > [Worker] > Cron Triggers
  • トリガーのみを変更する場合は wrangler triggers deploy を使用します
# If you only changed triggers (not code), use:
bunx wrangler triggers deploy

# Wait 15 minutes, then verify in dashboard

問題#2:ハンドラーがエクスポートされていない

エラー: Handler does not export a 'scheduled' method

ソース: よくあるデプロイエラー

発生する理由:

  • ハンドラーの名前が正確に scheduled になっていません
  • ハンドラーがデフォルトのエクスポートオブジェクトでエクスポートされていません
  • ESモジュール形式ではなくService Worker形式を使用しています

防止策:

// ❌ Wrong: Incorrect handler name
export default {
  async scheduledHandler(controller, env, ctx) { }
};

// ❌ Wrong: Not in default export
export async function scheduled(controller, env, ctx) { }

// ✅ Correct: Named 'scheduled' in default export
export default {
  async scheduled(controller, env, ctx) { }
};

Issue #3:UTC タイムゾーンの混乱

エラー: Cron が間違った時刻に実行される

原因: ユーザーの想定と実際の動作の違い

発生する理由:

  • すべての cron トリガーは UTC 時刻のみで実行されます
  • タイムゾーンの変換には対応していません
  • ユーザーはローカルタイムゾーンでの実行を想定しています

防止策:

ローカル時刻を手動で UTC に変換してください:

// Want to run at 9am PST (UTC-8)?
// 9am PST = 5pm UTC (17:00)
{
  "triggers": {
    "crons": ["0 17 * * *"]  // 9am PST = 5pm UTC
  }
}

// Want to run at 6pm EST (UTC-5)?
// 6pm EST = 11pm UTC (23:00)
{
  "triggers": {
    "crons": ["0 23 * * *"]  // 6pm EST = 11pm UTC
  }
}

// Remember: DST changes affect conversion!
// PST is UTC-8, PDT is UTC-7

ツール:


Issue #4:無効な Cron 式

エラー: Cron が実行されず、エラーも表示されない

原因: 検証が通知されずに失敗する

発生する理由:

  • 無効な cron 構文は、通知されずに失敗します
  • 検証はデプロイ時に行われますが、気づきにくい場合があります
  • よくある間違い:フィールドの順序が誤っている、無効な範囲を指定している

防止策:

# ❌ Wrong: Too many fields (6 fields instead of 5)
"crons": ["0 0 * * * *"]  # Has seconds field - not supported

# ❌ Wrong: Invalid minute range
"crons": ["65 * * * *"]  # Minute must be 0-59

# ❌ Wrong: Invalid day of week
"crons": ["0 0 * * 7"]  # Day of week is 0-6 (use 0 for Sunday)

# ✅ Correct: 5 fields, valid ranges
"crons": ["0 0 * * 0"]  # Sunday at midnight UTC

検証方法:

  • Crontab Guru で式を検証します
  • wrangler deploy の出力にエラーがないか確認します
  • --test-scheduled を使ってローカルでテストします

Issue #5:ES モジュール形式が不足している

エラー: Worker must use ES modules format

原因: レガシーな Service Worker 形式

発生する理由:

  • スケジュールされたハンドラーには ES モジュール形式が必要です
  • 古い Service Worker 形式には対応していません
  • コードベース内で形式が混在しています

防止策:

// ❌ Wrong: Service Worker format
addEventListener('scheduled', (event) => {
  event.waitUntil(handleScheduled(event));
});

// ✅ Correct: ES modules format
export default {
  async scheduled(controller, env, ctx) {
    await handleScheduled(controller, env, ctx);
  },
};

Issue #6:CPU 時間制限を超過した

エラー: CPU time limit exceeded

原因: 実行時間の長いスケジュールタスク

発生する理由:

  • デフォルトの CPU 制限は 30 秒です
  • 実行時間の長いタスクは制限を超過します
  • タイムアウトは自動延長されません

防止策:

オプション 1:wrangler.jsonc で CPU 制限を引き上げる

{
  "limits": {
    "cpu_ms": 300000  // 5 minutes (max for Standard plan)
  }
}

オプション 2:実行時間の長いタスクには Workflows を使用する

// Instead of long task in cron:
export default {
  async scheduled(controller, env, ctx) {
    // Trigger Workflow that can run for hours
    await env.MY_WORKFLOW.create({
      params: { task: 'long-running-job' },
    });
  },
};

オプション 3:小さなチャンクに分割する

export default {
  async scheduled(controller, env, ctx) {
    // Process in batches
    const batch = await getNextBatch(env.DB);

    for (const item of batch) {
      await processItem(item);
    }

    // If more work, send to Queue for next batch
    const hasMore = await hasMoreWork(env.DB);
    if (hasMore) {
      await env.MY_QUEUE.send({ type: 'continue-processing' });
    }
  },
};

必ず行うこと ✅

  1. 正確なハンドラー名を使う - scheduledHandler やその派生名ではなく、scheduled を使う必要があります
  2. ES モジュール形式を使う - addEventListener ではなく、デフォルトオブジェクトでエクスポートします
  3. UTC に変換する - すべての cron 時刻は UTC です。ローカルタイムゾーンから変換してください
  4. 15 分待つ - cron の変更が反映されるまで、最大 15 分かかります
  5. まずローカルでテストする - wrangler dev --test-scheduled を使います
  6. cron 構文を検証する - Crontab Guru を使います
  7. エラーを適切に処理する - ログを記録し、アラートを出し、必要に応じて再スローします
  8. ctx.waitUntil() を使う - 重要でない非同期処理に使います
  9. Workflows を検討する - 30 秒を超える CPU 時間が必要なタスクに使います
  10. 実行を監視する - ダッシュボードのログを定期的に確認します

絶対に行わないこと ❌

  1. ローカルタイムゾーンを前提にしない - すべての cron は UTC で実行されます
  2. 6 フィールドの cron 式を使わない - Cloudflare は 5 フィールド形式を使用します(秒は含みません)
  3. 変更が即座に反映されると期待しない - 反映には最大 15 分かかります
  4. Service Worker 形式を使わない - ES モジュール形式を使う必要があります
  5. エラー処理を忘れない - 捕捉されないエラーは通知されずに失敗します
  6. 制限を引き上げずに CPU 負荷の高いタスクを実行しない - デフォルトの制限は 30 秒です
  7. 曜日に 7 を使わない - 日曜日には 0 を使います(範囲は 0~6 のみ)
  8. テストせずにデプロイしない - まず必ず --test-scheduled でテストします
  9. 実行ログを無視しない - ダッシュボードで過去の失敗を確認できます
  10. テスト用のスケジュールをハードコードしない - 環境ごとの設定を使います

よくあるユースケース

references/common-patterns.md を読み込み、データベースのクリーンアップ、API データの収集、日次レポートの生成、キャッシュのウォームアップ、監視とヘルスチェック、データ同期、バックアップの自動化、サイトマップの生成、Webhook の処理、スケジュール通知など、実際に使われている 10 種類の cron パターンを確認してください。


TypeScript 型

// Scheduled event controller
interface ScheduledController {
  readonly cron: string;
  readonly type: string;
  readonly scheduledTime: number;
}

// Execution context
interface ExecutionContext {
  waitUntil(promise: Promise<any>): void;
  passThroughOnException(): void;
}

// Scheduled handler
export default {
  async scheduled(
    controller: ScheduledController,
    env: Env,
    ctx: ExecutionContext
  ): Promise<void>;
}

制限と料金

制限
機能無料プラン有料プラン
Worker ごとの Cron トリガー数3それ以上(ドキュメントを確認してください)
1 回の実行あたりの CPU 時間10 ms(平均)30 秒(デフォルト)、5 分(最大)
実時間30 秒15 分
メモリ128 MB128 MB
料金

Cron トリガーには Standard Workers の料金が適用されます。

  • Workers Paid Plan:月額 $5 が必要です
  • リクエスト:100 万リクエストあたり $0.30(無料枠の 1,000 万件を超えた後)
  • CPU 時間:100 万 CPU-ms あたり $0.02(無料枠の 3,000 万件を超えた後)

Cron の実行 = 1 リクエスト

例:

  • Cron を毎時実行(1 日 24 回)
  • 30 日 × 24 回の実行 = 月 720 回の実行
  • 1 回の実行あたり平均 50ms の CPU 時間

費用:

  • リクエスト:720 件(無料枠の 1,000 万件を大きく下回ります)
  • CPU 時間:720 × 50ms = 36,000ms(無料枠の 3,000 万件を下回ります)
  • 合計:月額 $5(サブスクリプション料金のみ)

高頻度の例:

  • Cron を毎分実行(1 日 1440 回)
  • 30 日 × 1440 回 = 月 43,200 回の実行
  • それでも無料枠の上限を下回ります
  • 合計:月額 $5

トラブルシューティング

問題:Cron が実行されない

考えられる原因:

  1. 変更がまだ反映されていない(15 分待ちます)
  2. Cron 式が無効です
  3. ハンドラーが正しくエクスポートされていません
  4. Worker がデプロイされていません

解決方法:

# Re-deploy
bunx wrangler deploy

# Wait 15 minutes

# Check dashboard
# Workers & Pages > [Worker] > Cron Triggers

# Check logs
# Workers & Pages > [Worker] > Logs > Real-time Logs

問題:ハンドラーは実行されるが失敗する

考えられる原因:

  1. ハンドラー内でエラーが捕捉されていません
  2. CPU 時間の上限を超えています
  3. 環境バインディングが不足しています
  4. ネットワークがタイムアウトしています

解決方法:

export default {
  async scheduled(controller, env, ctx) {
    try {
      await yourTask(env);
    } catch (error) {
      // Log detailed error
      console.error('Handler failed:', {
        error: error.message,
        stack: error.stack,
        cron: controller.cron,
        time: new Date(controller.scheduledTime),
      });

      // Send alert
      ctx.waitUntil(sendAlert(error));

      // Re-throw to mark as failed
      throw error;
    }
  },
};

エラーの詳細はダッシュボードのログを確認してください。


問題:実行時刻が正しくない

原因: UTC と現地時間の混同

解決方法:

希望する現地時間を UTC に変換します。

// Want 9am PST (UTC-8)?
// 9am PST = 5pm UTC (17:00)

{
  "triggers": {
    "crons": ["0 17 * * *"]
  }
}

ツール:


問題:ローカルテストが機能しない

考えられる原因:

  1. --test-scheduled フラグがありません
  2. エンドポイントが間違っています(/__scheduled である必要があります)
  3. Python Worker の場合(/cdn-cgi/handler/scheduled を使用します)

解決方法:

# Correct: Start with flag
bunx wrangler dev --test-scheduled

# In another terminal
curl "http://localhost:8787/__scheduled?cron=0+*+*+*+*"

本番環境へのデプロイ前チェックリスト

Cron トリガーを本番環境にデプロイする前に、以下を確認してください。

  • Crontab Guru で Cron 式を検証済み
  • デフォルトエクスポート内のハンドラー名が正確に scheduled
  • ES モジュール形式を使用(Service Worker 形式ではない)
  • 現地時間を UTC に変換済み
  • ログ記録を含むエラー処理を実装済み
  • 失敗時のアラートを設定済み
  • 必要に応じて CPU 上限を引き上げ済み(limits.cpu_ms)
  • 環境バインディングをテスト済み
  • --test-scheduled を使ってローカルでテスト済み
  • ステージング環境でデプロイをテスト済み
  • デプロイ後、反映のために 15 分待機済み
  • ダッシュボードのログで実行を確認済み
  • モニタリングとアラートを設定済み
  • スケジュールの詳細をドキュメントに反映済み

関連ドキュメント


最終更新日:2025-10-23 バージョン:1.0.0 メンテナー:Claude Skills Maintainers | [email protected]

コメント