DidoQ リアルタイム通知付きジョブキュー

DidoQ - 時間のかかる処理を、安心して待てるようにする

DidoQは、時間のかかる処理を裏側で確実に実行し、終わったら即座に通知する仕組みです。

たとえば「AIに長文を分析させる」「数千件のデータを集計する」といった処理は、ユーザーが画面で待っているには長すぎます。かといって「あとで見に来てください」では不親切です。

DidoQを使うと、こうした処理をバックグラウンドで確実に実行しながら、リアルタイムで進捗を画面に通知できます。途中でシステムがクラッシュしても、自動的に復旧して処理を続けます。

こんな場面で使えます

  • AIによるファクトチェック: ユーザーが入力した主張を、複数の情報源と照らし合わせて検証する(数分かかる)
  • レポート生成: 過去1年分のデータを集計してPDFレポートを作成する(数十秒〜数分)
  • 画像処理: アップロードされた動画を複数の解像度に変換する(数分〜数時間)
  • バッチ通知: 数千人のユーザーにメールやプッシュ通知を送信する

解決する3つの課題

1. 「処理が終わったか、何度も確認しないといけない」問題

従来の方法では、ユーザーが「更新ボタン」を何度も押したり、画面を再読み込みしたりする必要がありました。

DidoQの解決策: WebSocketを使って、処理が終わった瞬間に自動で通知します。更新ボタンは不要です。

2. 「サーバーが落ちたら、処理も消えてしまう」問題

メモリだけで処理を管理していると、サーバーがクラッシュした瞬間にすべての処理状況が失われます。

DidoQの解決策: すべての状態をデータベース(D1)に記録します。サーバーが復旧すると、自動的に処理を再開します。

3. 「処理が固まって、永遠に終わらない」問題

外部APIが応答しなくなったり、処理中に無限ループに陥ったりすると、ジョブが永遠に「処理中」のまま放置されます。

DidoQの解決策: タイムアウト検出機能により、一定時間応答がない処理は自動的に中断され、再試行されます。

仕組み:レストランの注文システムに例えると

DidoQの仕組みは、レストランの注文システムに似ています。

  1. 注文(ジョブの登録): お客さんが料理を注文します
  2. キッチン(処理の実行): 裏でシェフが料理を作ります
  3. 呼び出しベル(リアルタイム通知): 料理ができたら、お客さんの席にベルで知らせます
  4. 注文伝票(データベース): もしシェフが途中で倒れても、伝票があれば別のシェフが引き継げます

このシステムのおかげで、お客さんは席で安心して待っていられます。キッチンに何度も「まだですか?」と聞きに行く必要はありません。

技術的な特長

データベースが「真実の記録」

DidoQでは、すべてのジョブの状態をCloudflare D1(SQLiteデータベース)に保存します。メモリ上のキャッシュは高速化のためだけに使い、真の状態は常にデータベースから読み取ります。

これにより、システムが再起動しても、処理中だったジョブを正確に復元できます。

自動復旧の仕組み

DidoQは「アラーム」という仕組みを使って、定期的にデータベースをチェックします。もし処理が中断されていたら、そこから自動的に再開します。

人間が手動で復旧操作をする必要はありません。

ハートビートでタイムアウト検出

処理中のジョブは、定期的に「まだ生きてます」という信号(ハートビート)を送ります。この信号が一定時間途絶えると、DidoQは「何かおかしい」と判断し、処理を中断して再試行します。

複数の処理を並列実行(シャーディング)

DidoQはデフォルトで10個の「作業場」(シャード)を用意し、ジョブを分散して処理します。これにより、数千のジョブを同時に処理できます。

使い方の概要

サーバー側:ジョブを登録する

// ジョブをキューに追加
await enqueueJob(env, { tableName: 'jobs' }, {
  id: crypto.randomUUID(),
  userId: 'user-123',
  jobType: 'fact-check',
  payload: { claim: 'ユーザーが入力した主張' },
});

サーバー側:ジョブを処理する

export class FactCheckQueue extends DidoQDurableObject {
  protected async processJobImpl(job) {
    // AIに問い合わせて、ファクトチェックを実行
    const result = await checkFactWithAI(job.payload.claim);
    return { resultId: result.id };
  }
}

クライアント側:進捗をリアルタイムで表示する

function FactCheckPage() {
  const { status, isMonitoring } = useJobMonitor(
    jobId,
    { apiBase: 'https://api.example.com' },
    {
      onComplete: (resultId) => {
        // 処理完了!結果ページに移動
        router.push(`/results/${resultId}`);
      },
      onError: (error) => {
        toast.error('エラーが発生しました');
      },
    }
  );

  return (
    <div>
      <p>処理状況: {status}</p>
      {isMonitoring && <Spinner />}
    </div>
  );
}

信頼性を支える機能

  • 最大リトライ回数の制限: 何度も失敗する処理は、無限ループを防ぐため一定回数で停止します
  • タイムアウト自動検出: 長時間応答のない処理は自動的に中断され、再試行されます
  • ネットワーク切断対応: WebSocketが使えない環境では、自動的にポーリング(定期確認)に切り替わります
  • 重複通知の防止: 同じ完了通知を何度も送らないよう、内部で制御しています
  • イベント履歴の記録: すべての処理過程を記録し、トラブル時の調査に活用できます

技術スタック

DidoQは、次の技術を組み合わせて構築されています。

  • Cloudflare Workers: エッジで動作する高速なサーバーレス環境
  • D1: Cloudflare上のSQLiteデータベース(ジョブの状態を永続化)
  • Durable Objects: ステートフルな処理とリアルタイム通信を実現
  • WebSocket / Long Polling: クライアントへのリアルタイム通知
  • React Hooks: フロントエンドでの簡単な状態管理(オプション)
  • TypeScript: 型安全な開発体験

まとめ

DidoQは、時間のかかる処理を「確実に実行」し、「リアルタイムで通知」する仕組みです。

従来の「定期的にポーリングして確認する」方式や「メールで通知が来るまで待つ」方式と比べて、ユーザー体験を大きく向上させます。

しかも、サーバーがクラッシュしても自動復旧し、処理が固まっても自動でタイムアウトする信頼性を備えています。

Cloudflare Workersのエッジネットワーク上で動作するため、世界中どこからでも低遅延でアクセスできます。

まずはお気軽にご相談ください。目的や課題を丁寧にヒアリングし、
ご予算や納期に合わせた最適なご提案をいたします。

まずはお気軽にご相談ください。
目的や課題を丁寧にヒアリングし、
ご予算や納期に合わせた最適な
ご提案をいたします。

無料相談はこちら