mcpField
D
debug-production-renders

debug-production-renders

github.com/editframe云与 DevOps1973 次安装2 周前更新
代码仓库

关于 debug-production-renders

这是一项用于排查 Telecine 渲染工作流的运维技能,覆盖 Postgres、Valkey 队列和 Cloud Run Worker 日志。文档介绍状态与队列检查、故障分析,以及供工程师重试失败渲染的脚本。

主要功能

  1. 01检查渲染记录和片段状态
  2. 02查看 Valkey 队列与工作流状态
  3. 03查询 Cloud Run Worker 日志
  4. 04诊断 RPC 超时和并发问题
  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 工作服务日志。

快速开始

所有调试脚本都在 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 渲染视频的一个时间片段,将片段文件写入存储,并报告进度。
  5. render-finalizer -- 所有片段作业完成后自动触发。将片段文件合并为最终输出,并将渲染标记为已完成。

流水线由针对 video2.renders 中 INSERT 操作的 Hasura 事件触发。当所有子作业完成或任何作业在重试次数耗尽后失败时,工作流系统会自动将最终处理作业路由到相应队列。

队列名称、工作服务名称和资源分配在源文件中定义——请参见下文的“关键源文件”。

调试脚本

脚本用途
telecine/scripts/debug-render <id> [--redis] [--logs]主要调试工具:数据库状态、片段、错误;可选查看 Valkey 和日志
telecine/scripts/inspect-render.ts更底层的 Valkey 检查:工作流数据、带有等待时长的已认领作业、所有工作流键
telecine/scripts/check-queue.ts队列级 Valkey 状态:排队/已认领/失败计数、组织成员关系
telecine/scripts/restart-render.ts重启失败的渲染:重置数据库状态,并重新将初始化作业加入队列
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波形专项冒烟测试:直接向数据库插入渲染任务,并并发测试所有 ef-waveform 模式
telecine/scripts/consoleNode 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 -- 等待领取的作业键组成的有序集合
  • queues:{queueName}:claimed -- 正在处理的作业键组成的有序集合(分数 = 领取时间戳)
  • queues:{queueName}:completed -- 已完成的作业键组成的有序集合
  • queues:{queueName}:failed -- 已失败的作业键组成的有序集合
  • queues:{queueName}:jobs:{jobId} -- 序列化的作业数据(SuperJSON)
  • queues:{queueName}:orgs -- 包含有活动作业的组织键的有序集合

工作流级键(按渲染 ID 划分):

  • workflows:{renderId}:queued -- 工作流级别待处理作业的有序集合
  • workflows:{renderId}:claimed -- 已领取作业的有序集合
  • workflows:{renderId}:completed -- 已完成作业的有序集合
  • workflows:{renderId}:failed -- 已失败作业的有序集合
  • workflows:{renderId}:data -- SuperJSON 工作流负载(渲染配置)
  • workflows:{renderId}:status -- 工作流状态字符串

进度跟踪:

  • render:{renderId} -- 用于跟踪片段完成进度的 Redis 流

通过检查分数(领取时间戳)早于 10 秒的已领取作业,可以检测到停滞作业。

数据库表

渲染状态通过 Kysely(而非 Prisma)持久化到 Postgres。db 客户端从 @/sql-client.server 导入。

  • video2.renders -- 主渲染记录:状态、html、org_id、尺寸、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 开始 -- 获取数据库状态、错误详情和片段明细。
  2. 如果卡在 "rendering" 状态 -- 添加 --redis,查看作业是否已排队、已领取(可能停滞),或在 Valkey 中悄然失败。
  3. 如果 Valkey 状态不明确 -- 使用 inspect-render.ts 查看已领取作业的详细等待时间,使用 check-queue.ts 查看队列级别的计数。
  4. 如果需要工作进程日志 -- 使用渲染 ID,通过 gcloud 查询 Cloud Run 日志(参见上面的命令)。在本地开发环境中,使用 --logs 标志或 render-logs 脚本。
  5. 要重试 -- 使用 restart-render.ts 重置数据库状态并重新加入初始化作业。
  6. 要访问生产数据库 -- 使用 telecine/scripts/debug-prod-web --use-prod-db --shell 获取可连接生产数据库的容器。

诊断 Electron RPC 故障

片段渲染会因 RPC 超时而失败。堆栈跟踪会显示渲染进行到了哪一步:

  • RPC.ts:182 — 初始 5 s 计时器触发,未收到任何保持连接消息。Electron 从未开始渲染。原因:调度器打开的连接数超过单个本地容器的处理能力(见下文)、Electron 加载页面失败,或无法创建渲染上下文。
  • RPC.ts:153 — 渲染中途保持连接重置计时器触发。至少有一帧在挂起前完成渲染。原因:竞争条件中止了正在进行的 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 实例数量。本地每个队列只有一个容器。如果调度器打开的 WebSocket 连接数超过单个容器的预期(例如,30 个排队任务对应 30 个连接),那么超出工作器 WORKER_CONCURRENCY 配额的每个并发 renderFragment RPC 调用都会在 Electron 开始处理前,于 RPC.ts:182 超时。

两个调节项及其相互作用:

调节项生产环境本地开发
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 队列状态
  • 需要重启失败的渲染任务
  • 需要了解渲染流水线架构

评论

支持 Markdown