mcpField
D
debug-production-renders

debug-production-renders

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

debug-production-renders について

Telecine のレンダリングワークフローを調査する運用スキルです。Postgres、Valkey キュー、Cloud Run ワーカーログを対象に、状態確認、障害分析、失敗したレンダリングの再試行用スクリプトを説明します。

主な機能

  1. 01レンダリング記録とフラグメント状態の確認
  2. 02Valkey キューとワークフロー状態の確認
  3. 03Cloud Run ワーカーログの検索
  4. 04RPC タイムアウトと並行処理の問題を診断
  5. 05失敗したレンダリングの再起動

活用シーン

  1. 01キューをたどって停止したレンダリングを追跡
  2. 02ログと状態からフラグメントの失敗を調査
  3. 03初期化ジョブを再登録して失敗したレンダリングを再試行

インストール

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

$npx skills add https://github.com/editframe/skills --skill debug-production-renders

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

詳細

本番レンダーのデバッグ

Telecine のレンダリングは、Valkey(Redis 互換)を基盤とするキューベースのパイプラインを通じて処理されます。各レンダーは複数のキューを順に進むワークフローであり、それぞれのキューは専用の Cloud Run ワーカーサービスによって処理されます。レンダーをデバッグするには、Postgres データベース、Valkey のキュー状態、Cloud Run ワーカーのログという 3 つのレイヤーで状態を確認します。

クイックスタート

デバッグスクリプトはすべて docker 内で実行します。モノレポのルートから実行してください。

# Full render status: DB row, fragment breakdown, error detail
telecine/scripts/debug-render <render-id>

# Add live Valkey state (queued/claimed/completed/failed jobs)
telecine/scripts/debug-render <render-id> --redis

# Add docker compose log grep (local dev only)
telecine/scripts/debug-render <render-id> --logs

# All three
telecine/scripts/debug-render <render-id> --redis --logs

レンダーパイプラインの流れ

レンダーは次の順序でキューを進みます。

  1. process-html-initializer -- API の送信元から受け取った未処理の HTML を前処理します。
  2. process-html-finalizer -- ワークフローデータを設定し、render-initializer ジョブをキューに追加します。HTML パイプラインからレンダーパイプラインへつなぐ役割を担います。
  3. render-initializer -- レンダーソースをチェックアウトし、Electron RPC 経由でレンダー情報(寸法、長さ、fps)を抽出して、アセットのメタデータバンドルを作成した後、N 個のフラグメントジョブに処理を振り分けます。静止画像(png/jpeg/webp)の場合は、画像を直接レンダリングし、フラグメント処理をスキップします。
  4. render-fragment(並列で N 個)-- 各ジョブが Electron RPC 経由で動画の 1 つの時間区間をレンダリングし、フラグメントファイルをストレージに書き込み、進捗を報告します。
  5. render-finalizer -- すべてのフラグメントジョブが完了すると自動的に起動します。フラグメントファイルを結合して最終出力を作成し、レンダーを完了済みにします。

パイプラインは、video2.renders への INSERT に対する Hasura イベントによって起動します。ワークフローシステムは、すべての子ジョブが完了した場合、またはいずれかのジョブがリトライを使い切って失敗した場合に、finalizer キュージョブを自動的にルーティングします。

キュー名、ワーカーサービス名、リソースの割り当てはソースファイルで定義されています。詳しくは、以下の「主要なソースファイル」を参照してください。

デバッグスクリプト

スクリプト目的
telecine/scripts/debug-render <id> [--redis] [--logs]主なデバッグツール:DB の状態、フラグメント、エラー、オプションで Valkey とログ
telecine/scripts/inspect-render.tsより詳細な Valkey の調査:ワークフローデータ、処理中ジョブと経過時間、すべてのワークフローキー
telecine/scripts/check-queue.tsキューレベルの Valkey 状態:キュー内/処理中/失敗の件数、組織の所属状況
telecine/scripts/restart-render.ts失敗したレンダーを再起動:DB のステータスをリセットし、initializer ジョブを再度キューに追加
telecine/scripts/create-render.ts既存のレンダーの組織コンテキストを使ってテスト用レンダーを作成
telecine/scripts/render-logs [-f] <id>docker compose のログを検索し、initializer/fragment/finalizer サービスのログを確認
worktree smoke [branch](telecine/scripts/smoke-test.ts を実行)公開 API 経由のエンドツーエンドのスモークテスト
telecine/scripts/smoke-test-waveform.ts波形専用のスモークテスト:レンダーを DB に直接挿入し、ef-waveform のすべてのモードを並行して実行
telecine/scripts/consoleプロジェクトのインポートを利用できる Node REPL(db、valkey、queues を利用可能)

.ts スクリプトは次のように実行します:telecine/scripts/run tsx scripts/<script>.ts <args>

Cloud Run ログのクエリ

専用のログクエリ用スクリプトはありません。gcloud を直接使用してください。ワーカーは pino 経由で構造化 JSON をログに出力するため、jsonPayload フィルターを使用します。

# All render workers for a specific render ID
gcloud logging read \
  'resource.type="cloud_run_revision"
   AND resource.labels.service_name=~"telecine-worker-render"
   AND jsonPayload.renderId="<RENDER-ID>"' \
  --project=editframe --limit=100 --format=json

# Specific worker stage
gcloud logging read \
  'resource.type="cloud_run_revision"
   AND resource.labels.service_name="telecine-worker-render-initializer"
   AND jsonPayload.renderId="<RENDER-ID>"' \
  --project=editframe --limit=100

# Errors only across all workers
gcloud logging read \
  'resource.type="cloud_run_revision"
   AND resource.labels.service_name=~"telecine-worker"
   AND severity>=ERROR
   AND jsonPayload.renderId="<RENDER-ID>"' \
  --project=editframe --limit=50

Cloud Run サービス名は telecine-worker-{queue-name} という形式です。キュー名の一覧は telecine/deploy/resources/queues/configs.ts を参照してください。

Valkey キースキーマ

キューとワークフローでは、予測可能な Valkey キーパターンを使用します。これらを理解しておくと、スクリプトで対応できないケースでも状態を直接クエリできます。

キューレベルのキー(キュー名ごと):

  • queues:{queueName}:queued -- claim 待ちのジョブキーを格納する zset
  • queues:{queueName}:claimed -- 処理中のジョブキーを格納する zset(スコア = claim タイムスタンプ)
  • queues:{queueName}:completed -- 完了したジョブキーを格納する zset
  • queues:{queueName}:failed -- 失敗したジョブキーを格納する zset
  • queues:{queueName}:jobs:{jobId} -- シリアライズされたジョブデータ(SuperJSON)
  • queues:{queueName}:orgs -- アクティブなジョブがある組織キーを格納する zset

ワークフローレベルのキー(レンダー ID ごと):

  • workflows:{renderId}:queued -- ワークフローレベルでキューに入ったジョブを格納する zset
  • workflows:{renderId}:claimed -- claim 済みのジョブを格納する zset
  • workflows:{renderId}:completed -- 完了したジョブを格納する zset
  • workflows:{renderId}:failed -- 失敗したジョブを格納する zset
  • workflows:{renderId}:data -- SuperJSON ワークフローペイロード(レンダー設定)
  • workflows:{renderId}:status -- ワークフローのステータス文字列

進捗の追跡:

  • render:{renderId} -- フラグメント完了の進捗を記録する Redis ストリーム

claim タイムスタンプを表すスコアが 10 秒より古い claim 済みジョブを確認して、停滞したジョブを検出します。

データベーステーブル

レンダー状態は、Kysely(Prisma ではありません)を介して Postgres に永続化されます。db クライアントは @/sql-client.server からインポートします。

  • video2.renders -- メインのレンダーレコード:status、html、org_id、dimensions、fps、duration_ms、failure_detail、タイムスタンプ
  • video2.render_fragments -- セグメントごとのフラグメントレコード:render_id、segment_id、attempt_number、タイムスタンプ、last_error
  • video2.process_html -- HTML 処理レコード
  • video2.files -- ファイルレコード(process-isobmff および ingest-image で使用)

レンダーステータスの値:created -> queued -> rendering -> complete | failed

デバッグのワークフロー

  1. まず debug-render を実行します -- DB のステータス、エラー詳細、フラグメントの内訳を確認します。
  2. 「rendering」のまま止まっている場合 -- --redis を追加して、ジョブがキューに入っているか、claim 済み(停滞している可能性あり)か、Valkey で気づかれないまま失敗したかを確認します。
  3. Valkey の状態が不明な場合 -- inspect-render.ts で claim 済みジョブの経過時間を詳しく確認し、check-queue.ts でキューレベルの件数を確認します。
  4. ワーカーログが必要な場合 -- 上記のコマンドを参照し、レンダー ID を指定して gcloud で Cloud Run のログをクエリします。ローカル開発では、--logs フラグまたは render-logs スクリプトを使用します。
  5. 再試行する場合 -- restart-render.ts を使用して DB の状態をリセットし、イニシャライザーを再度キューに入れます。
  6. 本番 DB にアクセスする場合 -- telecine/scripts/debug-prod-web --use-prod-db --shell を使用して、本番データベースに接続できるコンテナを起動します。

Electron RPC の失敗の診断

フラグメントのレンダリングは RPC タイムアウトによって失敗します。スタックトレースから、レンダリングがどこまで進んだかがわかります。

  • RPC.ts:182 — 初期の 5 s タイマーが発火しました。キープアライブは一度も受信されていません。Electron はレンダリングを開始していません。原因:スケジューラーが単一のローカルコンテナで処理できる数を超える接続を開いた(下記参照)、Electron がページの読み込みに失敗した、またはレンダーコンテキストを作成できなかった。
  • RPC.ts:153 — レンダリング中にキープアライブリセットタイマーが発火しました。ハングする前に少なくとも 1 フレームがレンダリングされました。原因:競合状態により進行中の fetch が中止された(AbortError のケース)、フレームの処理に時間がかかりすぎた、またはセグメントの途中で Electron がクラッシュした。
AbortError / FrameController の競合

Electron のログに [EF_FRAMEGEN.beginFrame] error: [object DOMException] / AbortError: The user aborted a request が表示される場合、seekForRender 中に開始した fetch が、同時に発生した自動再レンダリングによってキャンセルされています。これはタイミングに依存する競合状態です。メディアの読み込み時に EFTemporal.updated() または EFTimegroup.updated() が発火して FrameController.abort() を呼び出し、進行中の GCS fetch を終了させています。

修正方法:自動再レンダリングを抑制するため、seekForRender の前に timegroup に data-no-playback-controller を設定します。これはレンダークローンでも使用される属性です。EF_FRAMEGEN.ts の initialize() と EFTemporal.ts/EFTimegroup.ts の updated() を確認してください。

ローカル開発環境でのスケジューラーの過剰スケーリング

本番環境では、MAX_WORKER_COUNT によってスケジューラーが起動する Cloud Run インスタンスの数を制御します。ローカル環境では、キューごとにコンテナーが 1 つあります。スケジューラーが単一のコンテナーの想定を超える WebSocket 接続を開くと(例:キューにある 30 個のジョブに対して 30 接続)、ワーカーの WORKER_CONCURRENCY の上限を超える同時 renderFragment RPC 呼び出しは、Electron が処理を開始する前に RPC.ts:182 でタイムアウトします。

2 つの設定値と、その相互作用は次のとおりです。

設定値本番環境ローカル開発環境
MAX_WORKER_COUNTコンテナー数をスケーリングしますdocker-compose の scale: と一致させる必要があります(通常は 1)
WORKER_CONCURRENCYコンテナーあたりのジョブ数MAX_WORKER_COUNT=1 の場合の実効並列度

どちらも telecine/.env から読み込まれます(ワーカーコンテナーでは env_file を介して、scheduler-go/docker-compose.yaml では ${VAR:-default} の置換を介して読み込まれます)。値を変更した場合は、新しい環境変数を適用するために telecine/scripts/docker-compose up -d を実行する必要があります(restart だけでは不十分です)。

主なソースファイル

  • telecine/scripts/debug-render.ts -- 主なデバッグツールの実装
  • telecine/scripts/inspect-render.ts -- 低レベルの Valkey レンダリング検査
  • telecine/scripts/check-queue.ts -- キューレベルの Valkey 状態チェッカー
  • telecine/scripts/restart-render.ts -- レンダリングの再起動/再試行ツール
  • telecine/lib/queues/Queue.ts -- キューの基底クラス、キーのパターン
  • telecine/lib/queues/Workflow.ts -- ワークフローの基底クラス、ワークフローキーのパターン
  • telecine/lib/queues/Job.ts -- ジョブのシリアライズ、エンキュー、停滞検出
  • telecine/lib/queues/units-of-work/Render/ -- レンダリングパイプラインのキュー/ワーカー定義
  • telecine/lib/queues/units-of-work/ProcessHtml/ -- HTML パイプラインのキュー/ワーカー定義
  • telecine/deploy/resources/queues/configs.ts -- 本番環境のキュー名とスケーリング設定
  • telecine/deploy/resources/queues/defineWorker.ts -- Cloud Run サービス定義テンプレート
  • telecine/deploy/resources/constants.ts -- GCP プロジェクト/リージョンの定数
  • telecine/lib/valkey/valkey.ts -- Valkey 接続設定

このスキルを使う場面

次の場合にこのスキルを使います。

  • 本番環境のレンダリングが停止している、失敗した、または予期しない結果になっている
  • レンダリングがどこで停止したのかを特定するため、パイプライン内で追跡する必要がある
  • 特定のレンダリングについて Cloud Run のログをクエリする必要がある
  • Valkey のキュー状態を調査または操作する必要がある
  • 失敗したレンダリングを再起動する必要がある
  • レンダリングパイプラインのアーキテクチャを理解する必要がある

コメント