【コード生成】同期と非同期(キュー & イベントループ)を正しく理解する:2025/12/15

プログラム

— Webアプリ設計で混同しがちな概念の整理 —

はじめに

YouTube動画の文字起こしやLLM処理のように、時間のかかる処理をWebアプリに組み込むとき、必ず議論になるのが「同期か、非同期か」という設計選択である。

進捗表示「だけ」を比べた表
観点同期 + SSE/WebSocket非同期ジョブ
進捗の表示可能可能
ページ更新耐性弱い強い
切断時の安全性低い高い
再開・再試行困難容易
複数ユーザースケール困難スケール容易
管理・監視ほぼ不可可能

本記事では、

  • 同期処理とは何か
  • 非同期処理とは何か
  • 「ジョブキュー型の非同期」と「async/await(イベントループ)」の違い
  • なぜ進捗表示が“できる/できない”ではなく“壊れやすさ”の問題になるのか

を、実装イメージと責務の違いに注目して整理する。


同期処理とは何か

同期処理の本質は、

呼び出し元が、処理の完了まで責任を持つ

という点にある。

典型的な同期処理

def main():
    extract_audio()
    transcribe()
    refine()
    export()
  • main() がすべての処理を順番に実行
  • 1つの処理が終わるまで次に進まない
  • Webアプリの場合、HTTPリクエストが開いている間ずっと処理が続く

同期処理の特徴

  • 実装はシンプル
  • 処理の流れが直感的
  • ただし
    • 処理が長いとタイムアウトしやすい
    • サーバリソースを占有し続ける
    • 接続が切れた瞬間に結果が失われやすい

同期でも進捗表示は可能か?

結論から言えば、可能である。

同期 + 進捗表示の典型手法

  • Server-Sent Events(SSE)
  • WebSocket

これにより、

  • 「音声抽出中」
  • 「文字起こし中」
    といったステータスを逐次フロントに送ることはできる。

しかし、問題はここではない

同期処理の本質的な弱点は、

  • 進捗が「そのHTTP接続にぶら下がっている」
  • 接続が切れた瞬間に、ユーザー視点では処理が消える
  • 再接続しても途中状態を確認できない

つまり問題は、

表示できるかどうかではなく、状態がどこに存在するか

である。


非同期処理とは何か(ジョブキュー型)

Webアプリで言う「非同期」とは、多くの場合、

処理の実行責任を、main(HTTPリクエスト)から切り離す

ことを意味する。

非同期(ジョブキュー型)の構造

def main():
    job_id = enqueue_job(youtube_url)
    return job_id
  • main() は処理を実行しない
  • 「仕事を登録する」だけで即レスポンス
  • 実際の処理は 別のワーカー が実行

構成要素

  • ジョブキュー(例:Redis)
  • ワーカープロセス
  • ジョブ管理DB(状態・進捗・エラー)

非同期処理の本質

  • 処理はHTTP接続と無関係に継続
  • 状態はDBに永続化される
  • ブラウザを閉じても処理は続く

非同期では進捗表示がどう変わるか

非同期では、進捗は「送られる情報」ではなく、

保存された状態を、取りに行く情報

になる。

job_id: 123
status: transcribing
progress: 62%
current_step: whisper

フロントエンドは、

  • ポーリング
  • WebSocket
    などで、この状態を取得して表示する。

結果として可能になること

  • ページ更新後も進捗確認可能
  • 別端末から進捗確認可能
  • 失敗時の原因分析・再実行が容易
  • 管理画面で全ジョブを俯瞰可能

async / await(イベントループ)は別物

ここで混同されがちなのが async / await である。

async / await の本質

await は、

処理を待つが、スレッドをブロックしない

という「待ち方」の指定である。

async def job():
    audio = await extract_audio()
    text = await transcribe(audio)
    refined = await refine(text)
  • 処理順はシーケンシャル
  • しかしI/O待ち中はCPUを解放
  • 複数タスクを効率よく捌ける

重要な注意点

  • async/await ≠ 非同期ジョブ
  • async/await ≠ 並列実行
  • async/await単一プロセス内の効率化

概念の整理表

概念意味
同期呼び出し元が完了まで責任を持つ
非同期(ジョブ)実行責任を別プロセスに委譲
async / await非ブロッキングな待ち方
並列同時にCPU/GPUを使用
プロセスOSレベルの実行単位

YouTube文字起こし系プロダクトへの適用

この種のプロダクトでは、

  • 処理時間が長い
  • 成功/失敗の分岐が多い
  • 再利用(再Q&A・再エクスポート)が多い

という特性がある。

推奨構成

  • Web層:軽量(同期 or async)
  • 重処理:非同期ジョブ(ワーカー)
  • ジョブ内部:async/await で順序制御

すなわち、

非同期ジョブ × async/await

が最も壊れにくく、拡張しやすい設計となる。


まとめ

  • 同期でも進捗表示はできる
  • しかし「壊れにくさ」「再開性」「運用性」は非同期が圧倒的に有利
  • async/await は非同期処理そのものではなく、効率的な実装手段

非同期を選ぶ理由は「かっこいいから」ではない。
長時間・不確実・再利用前提の処理を、プロダクトとして成立させるためである。

コメント

タイトルとURLをコピーしました