debug-production-renders について
Telecine のレンダリングワークフローを調査する運用スキルです。Postgres、Valkey キュー、Cloud Run ワーカーログを対象に、状態確認、障害分析、失敗したレンダリングの再試行用スクリプトを説明します。
主な機能
- 01レンダリング記録とフラグメント状態の確認
- 02Valkey キューとワークフロー状態の確認
- 03Cloud Run ワーカーログの検索
- 04RPC タイムアウトと並行処理の問題を診断
- 05失敗したレンダリングの再起動
活用シーン
- 01キューをたどって停止したレンダリングを追跡
- 02ログと状態からフラグメントの失敗を調査
- 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
レンダーパイプラインの流れ
レンダーは次の順序でキューを進みます。
- process-html-initializer -- API の送信元から受け取った未処理の HTML を前処理します。
- process-html-finalizer -- ワークフローデータを設定し、render-initializer ジョブをキューに追加します。HTML パイプラインからレンダーパイプラインへつなぐ役割を担います。
- render-initializer -- レンダーソースをチェックアウトし、Electron RPC 経由でレンダー情報(寸法、長さ、fps)を抽出して、アセットのメタデータバンドルを作成した後、N 個のフラグメントジョブに処理を振り分けます。静止画像(png/jpeg/webp)の場合は、画像を直接レンダリングし、フラグメント処理をスキップします。
- render-fragment(並列で N 個)-- 各ジョブが Electron RPC 経由で動画の 1 つの時間区間をレンダリングし、フラグメントファイルをストレージに書き込み、進捗を報告します。
- 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 待ちのジョブキーを格納する zsetqueues:{queueName}:claimed-- 処理中のジョブキーを格納する zset(スコア = claim タイムスタンプ)queues:{queueName}:completed-- 完了したジョブキーを格納する zsetqueues:{queueName}:failed-- 失敗したジョブキーを格納する zsetqueues:{queueName}:jobs:{jobId}-- シリアライズされたジョブデータ(SuperJSON)queues:{queueName}:orgs-- アクティブなジョブがある組織キーを格納する zset
ワークフローレベルのキー(レンダー ID ごと):
workflows:{renderId}:queued-- ワークフローレベルでキューに入ったジョブを格納する zsetworkflows:{renderId}:claimed-- claim 済みのジョブを格納する zsetworkflows:{renderId}:completed-- 完了したジョブを格納する zsetworkflows:{renderId}:failed-- 失敗したジョブを格納する zsetworkflows:{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_errorvideo2.process_html-- HTML 処理レコードvideo2.files-- ファイルレコード(process-isobmff および ingest-image で使用)
レンダーステータスの値:created -> queued -> rendering -> complete | failed
デバッグのワークフロー
- まず
debug-renderを実行します -- DB のステータス、エラー詳細、フラグメントの内訳を確認します。 - 「rendering」のまま止まっている場合 --
--redisを追加して、ジョブがキューに入っているか、claim 済み(停滞している可能性あり)か、Valkey で気づかれないまま失敗したかを確認します。 - Valkey の状態が不明な場合 --
inspect-render.tsで claim 済みジョブの経過時間を詳しく確認し、check-queue.tsでキューレベルの件数を確認します。 - ワーカーログが必要な場合 -- 上記のコマンドを参照し、レンダー ID を指定して
gcloudで Cloud Run のログをクエリします。ローカル開発では、--logsフラグまたはrender-logsスクリプトを使用します。 - 再試行する場合 --
restart-render.tsを使用して DB の状態をリセットし、イニシャライザーを再度キューに入れます。 - 本番 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 のキュー状態を調査または操作する必要がある
- 失敗したレンダリングを再起動する必要がある
- レンダリングパイプラインのアーキテクチャを理解する必要がある