Skip to content

✨ [Feature] BT 做种功能完整实现 #74

Description

@lingdiansr

BT 做种功能完整实现 — Issue 提案

基准:upstream/main (zerx-lab/FluxDown),当前完全没有 BT 做种能力。
BT 下载完成后直接断开所有 peer 连接,不参与上传分享。

关联上游 issue#42 希望添加上传限制 — 用户反馈"没有限制上传速度,家用宽带容易跑满影响其他设备",做种功能的上传限速直接覆盖此需求。


一、为什么需要做种功能

1.1 当前行为

BT 下载完成后的流程:

下载完成 → pause torrent(断开所有 peer) → 清理 staging 目录 → 任务标记为"已完成"

这是一个纯下载器的行为模型。对 BT 协议而言,pause 意味着:

  • 停止向 tracker/DHT announce
  • 关闭所有 peer 连接
  • 不再上传任何数据
  • 不响应其他 peer 的 piece 请求

1.2 对标产品

客户端 完成后的行为
qBittorrent 默认继续做种,支持分享率/时间/不活跃三重限制
Transmission 持续做种,支持全局和单种分享率控制
aria2 --seed-ratio / --seed-time 参数控制
FluxDown(当前) 不做种

1.3 用户价值

  1. BT 生态贡献:下载者同时也是上传者,维持 torrent 健康度
  2. 私有 tracker 准入:许多私有 tracker 要求最低分享率,不做种会被 ban
  3. 下载加速:做种期间保持 DHT/tracker 连接,后续添加同类种子时 peer 发现更快
  4. 用户控制感:可设置分享率/时间限制,自动管理做种生命周期

二、完整功能需求

2.1 做种状态模型

参考 qBittorrent 的成熟状态模型,引入以下任务状态:

下载中 → 校验中(新增) → 做种中(新增) → 已完成(含停止做种)
                      ↘ 做种暂停(新增)
状态 含义 UI 表现
下载中 正在下载数据 进度条 + 下载速度
校验中 (新增) BT 完成后的 piece hash 校验 进度条 100% + "校验中"标签
做种中 (新增) 正在上传给 peers 进度条 100% + 上传速度 + 做种时长
做种暂停 (新增) 用户或系统暂停了做种 可恢复
已完成 做种已停止,任务归档 绿色完成标记
已暂停 用户手动暂停下载
排队中 等待空闲下载槽位
错误 下载/校验失败
文件丢失 已完成任务的文件被外部删除

2.2 做种限制条件

默认规则:总分享率 ≥ 1.0 或 做种时间 ≥ 72 小时,满足任一即停止做种。用户可在设置中自由开启/关闭每个条件,条件之间可选"且/或"逻辑。

条件 默认值 说明
总分享率达到 1.0(关闭) uploaded_bytes / downloaded_bytes,含下载阶段的上传
做种后分享率达到 —(关闭) (uploaded_bytes - uploaded_at_completion) / downloaded_bytes
达到总做种时间 72 小时(开启) 首次进入做种开始计时
达到不活跃做种时间 30 分钟(关闭) 上传速度为 0 的持续时长

默认逻辑:总做种时间 ≥ 72h OR 总分享率 ≥ 1.0(用户可改为 AND)。

2.3 达到限制后的动作

默认动作:停止做种,任务转入已完成状态

可选动作(未来扩展):

  • 停止做种(默认推荐)
  • 删除任务及文件
  • 暂停任务

2.4 全局速度限制联动

全局下载速度限制同步应用于 BT 上传。 当前的独立上传限速字段 bt_upload_speed_limit_kbps 移除,BT 上传速率跟随全局 speed_limit_bytes。这样做的好处:

  • 用户不需要在两个地方设置速度限制
  • 避免了"下载限速但上传不限速"的半限速状态
  • 降低设置页复杂度

2.5 任务列表速度显示

BT 类型的任务条目,速度区域同时显示上传和下载速度

  • 下载中:显示 ↓ 下载速度;如有上传则同时显示 ↑ 上传速度
  • 做种中:显示 ↑ 上传速度
  • 无对应速度时自动隐藏该行,不显示 "—"

三、需要改动的模块

3.1 Rust 引擎层

3.1.1 新增 SeedingManagernative/engine/src/bt_seeding.rs

独立的做种生命周期管理器,不嵌入 SharedBtSession

  • 注册/注销 seeder(任务 ID → torrent handle 映射)
  • 评估做种限制(分享率、时间、不活跃时间)
  • 记录每次做种的起始上传量(用于"做种后分享率"计算)
  • 支持"达到限制后动作"的策略模式
  • 维持做种会话记录(用于重启恢复)

3.1.2 改造完成路径 — native/engine/src/bt_downloader.rs

BT 下载完成后的行为变更:

Before: finished → verify pieces → pause torrent → clean staging → done
After:  finished → verify pieces → clean staging → register seeder → keep alive

校验阶段

  • 校验期间任务状态设为"校验中"(新增状态码),UI 展示 校验中 标签
  • 校验进度可量化:hashed_pieces / total_pieces
  • 校验失败(phantom pieces)→ 自动重试下载受损 pieces

做种阶段

  • 校验通过后,torrent handle 保持活跃,注册到 SeedingManager
  • staging 目录在进入做种前清理(handle 指向最终文件路径)
  • 任务状态从"校验中" → "做种中"

3.1.3 扩展下载管理器 — native/engine/src/download_manager.rs

  • 定时器(30s)评估做种限制,触发停止/暂停动作
  • 全局速度限制联动 BT 上传:set_speed_limit() 同时调用 set_download_bpsset_upload_bps
  • 暂停做种:pause_seeding(task_id)bt.pause_task() + seeding_status = paused
  • 恢复做种:resume_seeding(task_id)bt.unpause_task() + register_seeder()
  • 停止做种:stop_seeding(task_id)bt.pause_task() + 任务转入已完成
  • 应用重启时恢复做种:扫描 seeding_status = active 的任务,重新 add_torrent 并注册 seeder
  • 会话保护:有活跃 seeder 时不释放 BT session

3.1.4 DB Schema 扩展 — native/engine/src/db.rs

tasks 表新增列:

列名 类型 默认值 说明
uploaded_bytes BIGINT 0 累计已上传字节数
seeding_status INTEGER 0 做种状态(0=none, 1=seeding, 2=ratio_reached, 3=time_reached, 4=inactive_reached, 5=user_stopped, 6=user_paused, 7=max_tasks, 8=task_deleted)
seeding_message TEXT '' 停止原因的文本说明

3.2 信号层 — native/hub/src/signals/mod.rs

TaskProgress 信号新增字段:

字段 类型 说明
uploaded_bytes i64 已上传字节数
upload_speed_bps i64 实时上传速率
seeding_status i32 做种状态码
seeding_message String 做种状态说明
checking_progress f64 校验进度(0.0~1.0,仅校验中状态有效)

ControlTask 新增 action:

  • 5 = 停止做种
  • 6 = 暂停做种
  • 7 = 恢复做种

3.3 Flutter UI 层

3.3.1 任务列表 (task_list_item.dart)

  • BT 任务的速度区域:同时显示 ↑ 上传速度和 ↓ 下载速度,无数据时自动隐藏
  • 做种中状态显示绿色"做种中"标签及上传速度
  • 校验中状态显示"校验中 n/m pieces"标签
  • 做种暂停显示琥珀色标签

3.3.2 详情面板 (detail_panel.dart)

  • 做种中:速度行切换为上传速度
  • 新增做种信息区:已上传量、分享率、做种时长、做种限制进度
  • 校验中:显示校验进度
  • 做种控制按钮:停止做种 / 暂停做种

3.3.3 侧边栏 (sidebar.dart + download_controller.dart)

  • 新增 "做种中" 状态 Tab,独立计数
  • 做种中 Tab 仅统计 seeding_status == active 的任务
  • "已完成" Tab 不再包含做种中的任务

3.3.4 设置页 (settings_page.dart)

BT 设置区重构做种限制 UI:

  • 移除独立的 "BT 上传速度限制" 输入框(由全局速度限制覆盖)
  • 改为条件开关模式:
    ☐ 总分享率达到       [1.0]
    ☐ 做种后分享率达到   [2.0]
    ☐ 达到总做种时间     [72] 小时
    ☐ 达到不活跃做种时间 [30] 分钟
    条件逻辑:[且 / 或 ▼]
    
  • 默认:仅"达到总做种时间 72h"开启,条件逻辑为"或"
  • 每个条件可独立开启/关闭
  • 新增 "达到限制后" 动作选择:停止做种 / 暂停做种 / 删除任务(默认停止做种)

3.3.5 下载任务模型 (download_task.dart)

  • 新增 SeedingStatus 枚举
  • 新增 uploadedBytesuploadSpeedBpsseedingStatusseedingMessageseedingStartedAtcheckingProgress 字段
  • isSeedingisChecking 计算属性
  • seedRatio 分享率计算
  • seedingDuration 做种时长

3.3.6 国际化 (translations.dart)

新增翻译 key(中/英):

  • 侧边栏 Tab:做种中 / Seeding
  • 状态标签:做种中、校验中、做种暂停
  • 详情面板:已上传、分享率、做种时间、校验进度
  • 设置页:做种限制标题、各类条件标签、条件逻辑选择
  • 通知:做种停止通知文案

3.4 Server 模式 (无头服务器)

native/server/src/actor.rs 同步所有 engine 层变更:做种定时评估、配置热更新。

3.5 aria2 JSON-RPC API (native/api/)

tellStatus 响应新增字段:

  • uploadLength(aria2 标准)
  • uploadSpeed(aria2 标准)
  • seedRatio(自定义扩展)
  • seedingStatus(自定义扩展)

四、实现方案

4.1 整体架构

┌─────────────────────────────────────────────────────────┐
│                   Flutter UI                            │
│  任务列表(双速显示)  详情面板(做种指标)  设置(条件开关) │
│  侧边栏(做种Tab)    通知(做种停止)                      │
├─────────────────────────────────────────────────────────┤
│              Rinf 信号层 (hub/signals)                   │
│  TaskProgress(扩展字段)  ControlTask(新增action)        │
├─────────────────────────────────────────────────────────┤
│              Engine 层                                   │
│  ┌───────────────┐  ┌────────────────────────────┐     │
│  │ SeedingManager│  │ DownloadManager             │     │
│  │ · register    │  │ · tick_seeding_eval (30s)   │     │
│  │ · unregister  │  │ · pause/stop/resume_seeding │     │
│  │ · eval_limits │  │ · 全局限速联动BT上传        │     │
│  │ · evict_lru   │  │ · 重启恢复做种              │     │
│  └───────────────┘  └────────────────────────────┘     │
│  ┌────────────────────────────────────────────────┐    │
│  │ SharedBtSession                                 │    │
│  │ · 保持 handle 活跃(做种期间不释放)             │    │
│  │ · 校验完成 → 注册 seeder                        │    │
│  └────────────────────────────────────────────────┘    │
├─────────────────────────────────────────────────────────┤
│              DB (SQLite / PostgreSQL)                   │
│  tasks: uploaded_bytes, seeding_status, seeding_message │
│  新增: seeding_sessions (做种历史)                      │
└─────────────────────────────────────────────────────────┘

4.2 分阶段实施

第一阶段:核心能力(必须)

  1. DB Schema + 数据模型

    • 新增列和 DB 读写 API
    • 引擎模型扩展(TaskInfo 等)
    • 信号扩展
  2. SeedingManager + 完成路径改造

    • 从零实现 SeedingManager
    • BT 下载完成后进入做种(不 pause)
    • 校验阶段中间状态暴露
    • 定时评估分享率/时间限制
    • 达到限制自动停止做种
    • max_seeding_tasks 限制强制执行(FIFO 逐出)
    • 做种暂停/恢复/停止控制
  3. 全局速度限制联动 BT 上传

    • set_speed_limit() 同时限制下载和上传
    • 移除 BT 设置中独立的上传限速输入框
  4. 重启恢复做种

    • 启动时扫描 seeding_status = active 的 completed 任务
    • 重新 add_torrent(利用 fastresume 跳过重复下载)
    • 注册 seeder

第二阶段:UI 与交互

  1. 任务列表双速显示 + 做种状态

    • BT 条目同时显示 ↑↓ 速度
    • 做种中/校验中/做种暂停状态标签
    • 无速度自动隐藏对应行
  2. 详情面板做种指标

    • 做种中切换为上传速度
    • 已上传量、分享率、做种时长
    • 限制进度条(分享率进度、时间进度)
  3. 侧边栏新增"做种中" Tab

    • 独立计数和筛选
    • "已完成" Tab 不再包含做种任务
  4. 设置页做种限制条件开关

    • 条件开关 + 且/或逻辑
    • 默认:总做种时间 ≥ 72h
    • 达到限制后动作选择

第三阶段:完善与健壮性

  1. aria2 API 暴露做种字段

    • tellStatus 返回上传量和做种状态
  2. 做种停止桌面通知

    • 限制触发停止时发送通知
  3. 做种会话历史记录

    • 新增 seeding_sessions
    • 每次做种的起止时间和上传量
  4. 集成测试

    • 完整做种生命周期测试
    • 限制触发测试
    • 重启恢复测试

4.3 关键设计决策

决策 选择 理由
分享率默认模式 总分享率 与 qBittorrent 一致,用户直觉
默认限制条件 总做种时间 ≥ 72h OR 总分享率 ≥ 1.0 兼顾贡献和用户便利
条件逻辑 用户可选 且/或 灵活性
达到限制默认动作 停止做种 最符合"限制"语义
上传限速 合并到全局速度限制 减少概念重叠,简化设置
校验态 新增独立中间状态 解决"99%卡住"的用户困惑
不活跃做种限制 支持但不默认开启 对热门种子过早停止
重启恢复做种 尝试恢复,失败则重置状态 不因重启静默丢失做种

五、预期效果

5.1 用户可见变化

  1. BT 下载完成后自动做种,不再直接停止
  2. 任务列表 BT 条目同时显示上传和下载速度,直观了解双向流量
  3. 侧边栏新增"做种中" Tab,一键筛选正在上传的任务
  4. 详情面板展示做种指标:已上传、分享率、做种时长、限制进度
  5. 设置页做种条件可自由组合,且/或逻辑切换
  6. "校验中"状态显示,不再误以为"卡在 99%"
  7. 做种停止时收到桌面通知
  8. 通过 aria2 API 可查询做种状态(外部客户端兼容)

5.2 行为变化

场景 当前 实现后
BT 下载完成 直接停止,断开所有 peer 进入做种,保持上传
全局限速设置 只限下载 同时限制下载和上传
应用重启 自动恢复做种(如果之前在做种)
分享率达到限制 自动停止做种并通知
做种时间达到限制 自动停止做种并通知
手动停止做种 停止上传,转入已完成
手动暂停做种 暂停上传,可恢复

六、风险评估

6.1 技术风险

风险 概率 影响 缓解措施
librqbit 不支持"已完成文件的 re-add 跳过下载" 重启恢复做种需重新校验所有 pieces 依赖 fastresume .bitv 文件;若无则走降级路径(重置 seeding_status)
做种期间 BT session 被 invalidate(配置变更触发) 活跃做种全部中断 invalidate_bt_session 前检查 has_seeders(),等待做种结束或强制通知用户
大量做种任务导致文件句柄耗尽 Windows 上可能触发 ERROR_SHARING_VIOLATION 限制 max_seeding_tasks 默认值(如 10),复用 librqbit 的 defer_writes_up_to 减少常开句柄
做种上传占用带宽影响下载体验 用户下载速度变慢 全局限速联动,用户可降低全局限速;未来可按 QoS 分配
重启批量恢复做种导致启动慢 多任务同时 add_torrent 延迟 限制 concurrent_init_limit(已有 3),串行恢复做种

6.2 产品风险

风险 概率 影响 缓解措施
用户不理解"为什么下载完了任务还在" 困惑,可能误报 bug 默认做种时间 72h 后自动停止;UI 明确标注"做种中";首次做种可弹 tooltip 说明
私有 tracker 用户被多记下载量 分享率异常 使用 librqbit 的 uploaded_bytes 统计,不做额外计算
默认不开启分享率限制,可能永远不做种停止 磁盘空间浪费 默认开启 72h 时间限制
全局限速联动与用户现有设置冲突 已有 BT 上传限速设置的用户需重新配置 迁移现有 bt_upload_speed_limit_kbps 值到全局 speed_limit_bytes

6.3 兼容性风险

风险 说明 缓解措施
DB 升级兼容 新增列对旧库无影响(add_column_if_missing 现有机制已覆盖
信号向后兼容 TaskProgress 新增字段需要 Dart 侧同步更新 所有字段带 #[serde(default)],旧版 Dart 忽略未知字段
aria2 API 兼容 新增字段对齐 aria2 规范 uploadLength/uploadSpeed 为标准 aria2 字段;seedRatio/seedingStatus 为自定义扩展

七、不做的事情(明确范围边界)

  1. 不做 Super Seeding(BEP-16):初始分发优化,小众场景
  2. 不做私有 tracker passkey 支持:需额外认证机制
  3. 不做 tracker scrape 协议:获取 swarm 统计,与做种核心流程无关
  4. 不做做种任务的优先级与带宽分配:复杂度高,先保持平等分配
  5. 不做 DHT announce 状态可视化:内部机制,用户无需感知
  6. 不做文件完整性定期校验:可手动重新校验,自动化收益有限

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions