主题
Job、Episode、Shot 三级状态机如何支持断点续跑和最小重跑?
题型:深入 · 讲清状态层级、提交点、幂等和结果未知。
建议回答
Job 表示一次整剧运行及其目标版本,Episode 和 Shot 是可独立调度、汇总和失效的子实体,真正执行时还要记录 nodeId 与 attemptId。每层状态至少区分 blocked、ready、running、succeeded、failed、canceled 和 invalidated,并保存输入版本、依赖快照、幂等键、租约、尝试次数、错误类别和产物引用。父级状态由子级事实汇总,不能由 Worker 随意直接改成成功。
断点续跑不是从“最后一行代码”继续,而是从最近一个已提交的业务边界重建 ready 集合。节点输出先写临时产物并完成 Schema 与业务校验,再以条件更新提交产物清单和 succeeded 状态;恢复时只信任已提交结果。队列通常至少一次投递,所以相同 node、输入版本和 attempt 的重复执行必须命中同一幂等记录,外部生成超时则先查询请求结果,把成功、失败和结果未知分开处理。
Shot 级最小重跑依赖显式依赖图。修改某个 Shot 的镜头描述时,只失效关键帧、视频等下游;修改全剧角色设定则可能失效多个 Episode,不能为了“最小”而复用语义上已经过期的产物。
关键权衡
- 状态粒度越细,恢复和观测越精确,但调度、存储和对账成本越高。
- 复用旧产物能节省生成成本,但必须把输入、Prompt、模型和设定版本纳入有效性判断。
- 状态库与产物库没有天然原子事务,需要提交清单、暂存区或补偿对账。
易错点
- 不要把“消息只消费一次”当作幂等保障,也不要承诺 Exactly-once。
- 不要在产物尚未可读时提前标记 succeeded,否则恢复会跳过实际缺失的步骤。