跳转到内容

架构 ​

Rivu 是原生 Go/MyGo 应用。docs/design 下的 HTML 是已确认的视觉参考,应用运行时不使用它。

状态归属 ​

根目录 main.go 调用 internal/app.Run。应用组合代码保持在单一的 internal/app 包中,下文的应用文件名均相对于该目录。

application.go 持有唯一会话、设置存储、更新器、托盘和可选窗口。关闭窗口只取消该窗口的草稿与后台工作,不关闭会话。原生菜单和命令面板共享 menu.go 中的稳定命令 ID。

mainWindow、settingsWindow 和 addWindow 分别管理视图状态。windowBase 仅共享原生生命周期、状态与可取消异步工作。主窗口区域位于 view_*.go,设置渲染与持久化分离。传输视图全部基于不可变观测渲染。theme.go 将设计颜色映射为 MyGo 主题值。UI SVG 符号来自已确认的原型,产品标识另有可编辑矢量源文件。

resources/embed.go 嵌入托盘图片与 SVG 资源,提供相对于 resources/ 的读取接口。应用在 icons.go 中解析和缓存 SVG,在 controls.go 中构建 UI 控件。internal/windowtask 管理可取消的窗口作业并丢弃过期回调,传输生命周期仍由 internal/session 管理。

传输状态 ​

internal/session 在工作线程侧通过互斥锁串行处理引擎操作与状态修改。深拷贝快照以原子方式发布,通过容量为 1、可合并的通道通知观察者。渲染不获取会话修改锁。测量每 500 毫秒刷新,意图变更在持久化后立即发布。

记录包含持久化运行意图、暂停批次成员、文件策略、元数据身份、目录、做种比例、上传总量与完成周期。实时引擎阶段不能覆盖手动暂停。引擎句柄同步执行并在停止时丢弃,分离的旧句柄不会通过延迟回调影响替代任务。

调度器最多允许配置数量的下载或校验任务,以及两个未解析元数据任务;做种不占下载名额。没有有效字节进度的内容任务和未解析元数据任务在 90 秒后让出名额,一分钟后重试;正在校验或做种的任务不受此规则影响。变更句柄前先规划准入,重新排序也遵守元数据限制。暂停会分离种子并停止节点活动,恢复时重新挂接并校验已有分片。

internal/torrent 适配固定开发提交 anacrolix/torrent v1.61.1-0.20260927071845-d913b30f520e。未解析磁力链接使用关闭 DHT/PEX 的独立客户端,禁用任意元数据 URL、Web Seed 与 WebTorrent。已解析私有种子遵循上游私有发现策略。

切换到内容客户端和重新挂接时保留磁力链接中的显式节点。队列重排使用不同排序值,最近请求优先。选中文件集合不变时,修改优先级保留完成周期。

文件边界 ​

元数据限制为 16 MiB,校验成员路径并拒绝冲突或大小写折叠后的重复路径。os.Root 将内容文件访问限制在选定目录。文件归属日志记录新文件的设备号与 inode,不覆盖无关替代文件。默认拒绝已有内容;显式接管单独记录已有文件身份,允许校验和修复,始终不授予废纸篓权限。

更改位置只引用已有目录,不移动旧文件;重置观测并保留暂停意图,每次挂接都重新校验。新文件先以临时名称创建,写入归属日志后通过排他重命名发布;日志写入失败不会在最终路径遗留未认领内容。发布前崩溃可能留下空临时文件,采取保守保留策略。

存储适配器处理分片与文件交叠,包括未选中文件中的字节。已验证进度只统计选中字节。导入空间检查计算选中分片与实际文件数据交集的并集,包含共享分片交叠但排除 v2 填充。来源保留分片长度与文件偏移,缺少几何信息的旧记录保守估计完整大小。每次挂接都重新校验,不把缓存百分比当作完整性证据。

文件几何信息被缓存,每次 I/O 查找相交文件。选中的空文件在准入时通过归属日志创建,无需请求相邻分片。元数据验证在引擎准入前拒绝错误的 v2 根哈希与不一致的混合种子分片数量。

移除默认保留文件。移到废纸篓前先持久化移除记录,再分离引擎、检查共享路径和文件身份,最后逐个调用原生 API。部分结果会保存,失败保持可见并可重试,绝不使用永久删除。

持久化与退出 ​

设置和会话分别使用 schema 2 的 JSON 文件,会话可从 schema 1 迁移。先写元数据,再写会话引用。同目录临时文件同步后原子重命名,macOS/Linux 随后同步父目录。重命名后提交结果不确定时阻止写入,直到显式重新加载。文件权限仅对当前用户开放。上传统计每 15 秒保存一次,崩溃时最多落后一个区间,孤立元数据保守保留。

损坏或较新版本文件保持原样并阻止写入,文件菜单提供修复后显式重新加载。暂停保存失败时保持句柄停止并展示错误。维护屏障在退出或更新安装期间阻止新准入。普通恢复不能解除持久化恢复锁,必须成功重新加载。退出请求同步拦截,再由工作线程保存和关闭,最后请求原生退出。

原子替换不构成跨设置、会话、元数据与文件系统的事务,发布前请检查实现状态中的验收缺口。

功能模块 ​

会话生命周期位于 manager.go;commands.go 在副作用前验证完整批次。import.go、persistence.go、recovery.go、removal.go、observation.go 和 snapshot.go 在同一互斥锁下各负其责。CommandKind、Phase、PauseReason 使用命名常量。internal/problem 携带与语言无关的错误码和上下文,界面在渲染时翻译恢复提示。

internal/torrent/preview.go 使用独立客户端与临时存储根,永久禁用内容准入。预览 45 秒超时,随添加窗口取消或关闭;确认草稿后持久化已认证元数据和文件优先级。

标签是持久任务属性,可在详情编辑、工具栏筛选。文件树缓存路径结构、支持搜索与展开,目录优先级作为一个完整命令验证。每页仅渲染 60 行,主任务列表使用稳定 ID 的 MyGo 虚拟 List。

internal/config/schedule.go 计算每日本地时间限速,支持跨午夜。手动慢速模式独立覆盖限速。做种时长是累计有效做种时间,随会话统计保存;比例或时长均可停止任务。显式恢复可覆盖已达到的做种目标,定时限速始终不修改运行意图。

internal/watchfolder 从普通 .torrent 文件读取最多 16 MiB,要求两次间隔 10 秒扫描内容一致,将相同字节交给解析器。独立原子账本阻止重启或移除任务后重复导入。坏种子不阻塞其他文件。监视默认关闭,使用默认目录及配置标签,不删除源文件,也不自动接管已有内容。

HTTP/UDP Tracker 结果和重试时间每 5 秒从固定引擎的 WriteStatus 表读取。版本相关解析器位于 internal/torrent/diagnostics.go,通过本地 HTTP Tracker 验证。诊断行不展示原始输出、URL 凭据、路径或查询参数;原始 Tracker URL 保留在来源元数据中,使复制的磁力链接可以保留私有 Tracker 凭据。错误归类为 DNS、超时、拒绝、授权或通告。未知格式显示诊断不可用,升级依赖必须运行契约集成测试。

支持 macOS、Windows 和 Linux 的原生 BitTorrent 应用。