Files
MoviePilot/docs/subscribe-lifecycle.md

117 lines
13 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.
# 订阅生命周期与订阅模式
本文说明主程序当前订阅领域的业务语义、字段所有权和使用方式,供维护订阅搜索、下载、进度刷新、重置和插件协同时参考。
## 核心模型
订阅是一条持续运行的媒体目标。它把用户想要的内容、搜索下载策略、已下载事实和完成进度保存在同一个订阅记录中。
订阅链路围绕四类状态工作:
| 状态类别 | 主要字段 | 含义 | 写入入口 |
| --- | --- | --- | --- |
| 目标范围 | `type`、`season`、`start_episode`、`total_episode` | 订阅需要覆盖的媒体范围。电影视为单个目标;电视剧按季和集范围处理。 | 新增订阅、订阅编辑、剧集刷新 |
| 下载事实 | `note`、`downloaded_tracks`、`episode_priority` | 主程序或可信回填入口确认已经存在或已经下载的目标。`note` 表示影视/单曲事实,`downloaded_tracks` 保存专辑已接受资源中的去重音轨键,`episode_priority` 表示电视剧每集已知下载质量。 | 下载事实入口、backfill 入口、reset 入口 |
| 进度摘要 | `lack_episode`、`current_priority`、`completed_episode`、`completed_tracks` | 面向搜索、完成判定和展示的进度。`current_priority` 是当前洗版模式的资源准入基线;`completed_episode` 和 `completed_tracks` 由响应层按当前事实计算。 | progress 刷新入口、下载事实入口、响应构造 |
| 生命周期状态 | `state`、`last_update` | 订阅是否继续搜索,以及最近一次系统写入时间。 | 搜索下载流程、完成订阅、reset、状态更新 |
字段所有权应保持集中:下载事实入口写事实,progress 刷新入口写派生进度,完成入口写完成状态,普通更新入口不应绕过这些语义直接改派生字段。
## 生命周期
| 阶段 | 触发来源 | 主程序行为 | 关键输出 |
| --- | --- | --- | --- |
| 创建订阅 | 用户、API、Agent、插件 | 记录媒体目标、订阅模式、季集范围、保存路径和下载策略。 | 初始订阅记录 |
| 搜索匹配 | 定时任务、手动搜索、RSS/站点刷新 | 按订阅目标和模式过滤候选资源,计算需要下载或升级的目标。 | 匹配候选、待下载上下文 |
| 下载选择 | 下载链路 | 将候选资源交给下载器;专辑下载层从文件清单提取可识别音轨键,不再按当前种子文件数拦截。 | 下载上下文、剩余缺口 |
| 事实记录 | 下载任务添加成功或可信 backfill | 写入 `note`,专辑合并 `downloaded_tracks`,电视剧同步写入或提升 `episode_priority`;全集洗版仅在下载层确认完整覆盖后提升 `current_priority`。 | 订阅下载事实快照 |
| 进度刷新 | 下载流程、backfill、剧集范围变化、显式刷新 | 普通电视剧按媒体库缺失结果刷新 `lack_episode`;电视剧洗版按目标范围和按集事实刷新 `lack_episode`,仅分集洗版从按集事实派生 `current_priority`。 | 进度字段 |
| 完成判定 | 下载流程末端、强制完成 | 根据媒体类型和订阅模式判断是否完成,完成前允许完成检查事件否决。 | 订阅历史、完成状态 |
| 重置/回填 | 用户操作、插件、维护工具 | reset 清空事实和进度;backfill 写入调用方确认的外部存在事实。 | 新事实快照和进度摘要 |
## 订阅模式
MoviePilot 当前以媒体类型和洗版方式组合出常用订阅模式。普通电视剧订阅和分集洗版都是“按集目标”订阅:前者每集下载一次即可,后者允许同一集继续升级质量。全集洗版是整体资源质量目标,整包候选需要完整覆盖目标范围。
| 模式 | 适用媒体 | 目标口径 | 下载事实 | 进度口径 | 完成口径 | 典型用途 |
| --- | --- | --- | --- | --- | --- | --- |
| 电影普通订阅 | 电影 | 单个电影目标 | `note=[1]` 表示电影已下载。 | 不维护电视剧缺集进度。 | 有下载或强制完成即可完成。 | 追新电影、补电影库 |
| 电影洗版 | 电影 | 单个电影目标的整体质量 | `note=[1]` 表示电影已下载。 | `current_priority` 表示当前电影资源质量。 | `current_priority == 100` 或完成策略满足时完成。 | 用更高质量版本替换已有电影 |
| 普通电视剧订阅 | 电视剧 | 季内目标集范围 | `note` 记录已存在或已下载集;`episode_priority` 记录每集已知下载质量。 | `lack_episode` 来自媒体库缺失结果。 | 目标范围无缺集时完成。 | 追剧、补缺集 |
| 分集洗版 | 电视剧 | 季内目标集范围 | `note` 记录存在事实;`episode_priority` 记录每集质量。 | `lack_episode` 统计从未下载过任何版本的集;`current_priority` 是目标范围最低已知质量。 | 目标范围内每集达到顶级质量时完成洗版。 | 对单集逐步升级质量 |
| 全集洗版 | 电视剧 | 完整目标集范围的整包质量 | 整包下载确认完整覆盖后,按目标范围写 `note` 和 `episode_priority`,并提升全集准入基线 `current_priority`。 | `current_priority` 表示全集模式的资源准入基线;保留的按集事实不参与候选过滤。 | `current_priority == 100` 或完成策略满足时完成。 | 用完整季包替换已有剧集 |
| 普通专辑订阅 | 音乐专辑 | 专辑总曲目范围 | 每次成功添加资源后合并去重的 `downloaded_tracks`。 | `completed_tracks` 为已累计曲目数,不能超过 `total_tracks`。 | 累计曲目数达到 `total_tracks` 后完成;单个不完整资源也可继续累计。 | 分批收集不同资源中的专辑曲目 |
## 按集订阅与全集洗版
普通电视剧订阅和分集洗版共享同一个按集事实源:
- `note` 表示某一集已经存在或已经下载。
- `episode_priority` 表示某一集已知的下载质量,缺失 key 表示没有质量事实。
- `lack_episode` 只表达“还缺多少集没有任何版本”,不表达“还有多少集需要升级质量”。
- `current_priority` 对分集洗版是目标范围内最低已知质量摘要,缺失质量事实按 `0` 参与计算。
普通专辑订阅使用独立音轨事实:下载层从种子文件清单提取盘号、曲序或归一化曲名组成的稳定键,订阅事实入口跨轮次合并并去重。接口只返回派生的 `completed_tracks`,不暴露内部音轨键;达到 `total_tracks` 前保持订阅,达到后才进入完成流程。
因此普通电视剧订阅和分集洗版可以互相转换。普通订阅下载产生的按集质量事实可被分集洗版继续使用;分集洗版产生的 `note` 也可被普通订阅继续作为已下载事实。
全集洗版关注完整目标范围的整体资源质量。整包候选必须完整覆盖 `[start_episode, total_episode]`,不是只覆盖当前缺口集。下载层确认完整覆盖后,主程序才可提升全集 `current_priority`,并在资源缺少显式集数时按目标范围补写按集事实。`episode_priority` 在全集模式中继续只升不降,供以后切回分集洗版使用,但不参与全集候选过滤和完成判断。
全集目标范围扩大后,原整包不再能证明覆盖新范围,因此全集准入基线 `current_priority` 重置为 `0`;目标范围缩小时,原整包仍覆盖新范围,保留该基线。
## 字段语义
| 字段 | 语义 | 关键约束 |
| --- | --- | --- |
| `note` | 已存在或已下载的电影项/电视剧集。 | 电影使用 `[1]`;电视剧使用集数列表。 |
| `downloaded_tracks` | 专辑已接受资源中的去重音轨稳定键。 | 只存在于活动订阅内部事实;API 通过 `completed_tracks` 暴露数量。 |
| `episode_priority` | 电视剧按集质量事实,键为集数,值为下载优先级。 | 只升不降;普通订阅和洗版订阅都可以写入。 |
| `lack_episode` | 电视剧目标范围内仍缺少任意版本的集数。 | 普通订阅来自媒体库缺失结果;洗版订阅按 `note` 和 `episode_priority > 0` 计算。 |
| `current_priority` | 当前洗版模式的资源准入基线。 | 电影和全集洗版由对应模式的受控入口维护;分集洗版按目标范围内最低已知质量刷新。 |
| `completed_episode` | 展示用完成集数。 | 分集洗版按顶档剧集数计算,全集洗版按整包准入基线是否达到顶档计算;不作为主要事实源。 |
| `completed_tracks` | 展示用已完成专辑曲目数。 | 由 `downloaded_tracks` 去重计数并截断到 `total_tracks`;不作为写入字段。 |
| `state` | 订阅运行状态。 | 完成、暂停、重置等入口按业务状态维护。 |
## 用户视角
| 想要做什么 | 推荐模式 | 行为说明 | 注意事项 |
| --- | --- | --- | --- |
| 新剧更新后自动下载 | 普通电视剧订阅 | 每集下载到任意版本即可,后续缺集继续追。 | 下载过的集会作为事实保留,后续可切到分集洗版。 |
| 已有剧集想逐集升级质量 | 分集洗版 | 每集按质量继续升级,达到顶级质量后不再下载该集。 | 低质量已下载集不计入缺集,但仍会作为待升级目标。 |
| 想用完整季包替换整季 | 全集洗版 | 优先寻找完整覆盖目标范围的整包资源,并按全集准入基线判断是否下载。 | 整包必须覆盖目标集范围,不只是覆盖当前缺口。 |
| 新电影自动下载 | 电影普通订阅 | 下载到电影后完成订阅。 | 电影没有分集事实。 |
| 电影已有版本想升级 | 电影洗版 | 用 `current_priority` 表达当前电影质量,下载更高质量版本。 | 完成策略按电影整体质量判断。 |
| 手动入库或插件扫描到已有集 | backfill | 可信调用方写入已存在集;可选择是否提供 quality priority。 | `priority=None` 只表达存在事实;提供有效 priority 才表达质量事实。 |
## 维护边界
### 自动搜索与站点恢复
新订阅保留一分钟编辑时间。暂停订阅后,已经入队的新订阅搜索、定时搜索及站点恢复任务也会停止;
正在执行的自动搜索在下一个安全边界退出,并在下载器提交前再次检查暂停状态。已经提交给下载器的
任务不受订阅暂停影响。手动或指定订阅搜索仍可对暂停订阅执行一次补搜;需要停止本次补搜时,
应取消对应搜索批次。
搜索及下载提交沿用同一执行上下文,不会为了补搜临时启用订阅,也不会在搜索无结果时恢复订阅。
下载成功后插件可以根据关联订阅的下载事件恢复订阅,已经完成的订阅仍按正常完成规则收口。
`last_search` 记录完整搜索轮次的开始时间,供订阅独立周期或系统周期判断下一次搜索是否到期。
因站点暂时不可用而仅补查剩余站点时,不刷新此时间,避免坏站点持续推迟正常站点的新一轮搜索。
同一轮恢复保留待搜索站点;经过到期筛选的新周期会把尚未运行的恢复任务重新覆盖当前启用站点。
正在执行的任务保持原范围,由后续周期调度接续,不改变已开始的下载副作用。
站点等待不代表搜索失败。其它站点仍在执行时保持搜索状态;本轮结束并保存续跑时间后才进入等待。
订阅搜索的同站唯一在途预算、站点访问间隔和错误冷却始终生效。机制审查及后续优化边界见
[订阅搜索机制审查](refactor/subscription-search-review.md)。
### 事实写入
- 公共创建与普通订阅编辑只负责目标和配置变更,不直接维护下载事实和进度摘要;Agent 或维护工具需要修正运行事实时,应使用受控的内部工具或领域入口。
- 主程序下载链路产生的电视剧下载必须同时维护 `note` 和 `episode_priority`。
- backfill 入口只接收调用方确认的外部存在事实,不主动扫描媒体库。
- progress 刷新入口负责把当前事实转换为 `lack_episode`,并仅为分集洗版派生 `current_priority`;全集准入基线由模式转换、确认完整覆盖的整包下载、目标范围变化,以及插件回滚或显式完成入口维护。
- 插件可以调用主程序公开入口补事实或刷新进度,不应复制主程序缺集、洗版完成或当前优先级计算规则。
## 智能分页搜索的生命周期
影视订阅的搜索任务可以分批提交:已提交部分集数后继续翻页寻找其余缺集,进度保存在 `searchsession`,任务进入终态时删除。`download_started` 只表示已越过下载副作用边界;分页任务要等 `scan_finished` 才算本轮结束。每批只下载已就绪的集,剩余缺集和订阅完成判断仍走原有流程;本轮结束时按当前订阅重新计算缺集,不回写总集数。策略和恢复规则见 [订阅补全搜索与手动分页](smart-search.md)。