feat: package docker deployment and publish flow

This commit is contained in:
theshy
2026-04-22 16:20:03 +08:00
parent 055474360e
commit 2146687dc6
178 changed files with 24318 additions and 20855 deletions

View File

@ -1,271 +1,271 @@
# 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 主状态来源
# 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 主状态来源