Files
biliup-next/docs/state-machine.md

272 lines
5.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# State Machine
## Goal
定义 `biliup-next` 当前实现使用的任务状态机,并明确数据库状态与工作区 flag 的职责边界。
状态机目标:
- 让每个任务始终有明确状态
- 支持失败重试和人工介入
- 让 UI 和 API 可以直接消费状态
- 保证步骤顺序和依赖关系清晰
## State Model
任务状态分为两层:
- `task status`:任务整体状态
- `step status`:任务中每一步的执行状态
## Task Status
### Core Statuses
- `created`
- `running`
- `transcribed`
- `songs_detected`
- `split_done`
- `published`
- `commented`
- `collection_synced`
### Failure Statuses
- `failed_retryable`
- `failed_manual`
### Terminal Statuses
- `collection_synced`
- `failed_manual`
## Step Status
每个步骤都独立维护自己的状态。
- `pending`
- `running`
- `succeeded`
- `failed_retryable`
- `failed_manual`
- `skipped`
## Step Definitions
### ingest
负责:
- 接收输入视频
- 基础校验
- 创建任务记录
### transcribe
负责:
- 生成字幕
- 记录字幕产物
### song_detect
负责:
- 识别歌曲列表
- 生成 `songs.json``songs.txt`
### split
负责:
- 根据歌单切割视频
- 生成切片产物
### publish
负责:
- 上传纯享版视频
- 同 session 多个 task 时,只由 anchor task 真正执行上传
- 聚合同 session 的全部 `clip_video`
- 成功后把同一个 `bvid` 写回整组 task
### comment
负责:
- 发布评论
- 置顶评论
- split 评论在 session 级聚合为 `P1/P2/P3`
- full 评论在 session 级聚合为 `P1/P2/P3`
- 同一 session 的评论只由 anchor task 执行一次
### collection_a
负责:
- 将完整版视频加入合集 A
### collection_b
负责:
- 将纯享版视频加入合集 B
## State Transition Rules
### Task-Level
```text
created
-> running
-> transcribed
-> running
-> songs_detected
-> running
-> split_done
-> running
-> published
-> running
-> commented
-> running
-> collection_synced
```
说明:
- `running` 是任务级瞬时状态,表示当前已有某个 step 被 claim 并正在执行。
- 当该 step 成功结束后task 会回到对应业务状态,例如 `transcribed``split_done``published`
- 当前实现中未使用 `ingested``completed``cancelled` 作为 task 状态。
### Failure Transition
任何步骤失败后:
- 若允许自动重试:任务进入 `failed_retryable`
- 若必须人工介入:任务进入 `failed_manual`
重试成功后:
- 任务回到该步骤成功后的下一个合法状态
## Dependency Rules
- `transcribe` 必须依赖 `ingest`
- `song_detect` 必须依赖 `transcribe`
- `split` 必须依赖 `song_detect`
- `publish` 必须依赖 `split`
- `comment` 必须依赖 `publish`
- `collection_b` 必须依赖 `publish`
- `collection_a` 通常依赖外部完整版 BV可独立于 `publish`
## Session Semantics
当多个 task 属于同一个 `session_key` 时,系统会引入 session 级语义:
- `split` 仍然保持 task 级
- `publish` 升级为 session 级
- `comment` 升级为 session 级
当前 anchor 规则:
- 同一 session 内按 `segment_started_at` 升序排序
- 最早那个 task 作为 anchor
当前 session 级行为:
- `publish`
- 只有 anchor task 执行真实上传
- 其余 task 复用同一个纯享 `BV`
- `comment.split`
- 只有 anchor task 对纯享版视频发评论
- 评论内容按 `P1/P2/P3` 聚合
- `comment.full`
- 只有 anchor task 对完整版视频发评论
- 评论内容按 `P1/P2/P3` 聚合
## Special Case: Collection A
合集 A 的数据来源与主上传链路不同。
因此:
- `collection_a` 不应阻塞主任务完成
- `collection_a` 可作为独立步骤存在
- 任务整体完成不必强依赖 `collection_a` 成功
当前实现:
- `collection_synced` 表示当前任务已经完成既定收尾流程。
- `collection_a` / `collection_b` 仍作为独立 step 存在,但系统暂未额外引入 `completed` 状态。
## Retry Strategy
### Retryable Errors
适合自动重试:
- 网络错误
- 外部 API 临时失败
- 上传频控
- 外部命令短时异常
### Manual Errors
需要人工介入:
- 配置缺失
- 凭证失效
- 文件损坏
- provider 不可用
- 标题无法匹配完整版 BV
## Persistence Requirements
每次状态变更都必须落库:
- 任务状态
- 步骤状态
- 开始时间
- 结束时间
- 错误码
- 错误信息
- 重试次数
## Flags And Files
工作区中的 flag 文件仍然存在,但它们不是 task 主状态的权威来源。
当前职责划分:
- 数据库:
- task 状态
- step 状态
- 重试信息
- 结构化上下文
- 工作区文件与 flag
- 外部副作用是否已执行
- 产物是否已落地
- 评论/合集等交付标记
换句话说:
- “任务现在处于什么状态”以数据库为准。
- “某个外部动作是否已经做过”可以由工作区 flag 辅助表达。
## UI Expectations
UI 至少需要直接展示:
- 当前任务状态
- 当前正在运行的步骤
- 最近失败步骤
- 重试次数
- 是否需要人工介入
## Non-Goals
- 不追求一个任务多个步骤完全并发执行
- 不把工作区 flag 文件当作 task 主状态来源