跳转到内容

架构

进阶

动手做大改动之前,先弄清代码放在哪里、要守哪些规则。

HolyArrs 是一个 Go 程序,Web 应用内置在里面。它在端口 6262 上提供 Web 应用和 JSON API,数据存在配置文件夹里的 2 个 SQLite 文件中。它会向外调用下载器、来源(通过 Jackett 或 Prowlarr)、媒体服务器、通知渠道和 HolyArrs 元数据服务器。

跟着一条请求走一遍。有人在探索页请求一部电影。

  1. requests 记下这条请求。
  2. 批准之后,movies 向 sources 要资源。
  3. mediafiles 里的挑选规则给它们打分。
  4. downloads 把最好的那个发给下载器。
  5. 下载完成后,mediafiles 导入文件。
  6. mediaservers 和 alerts 收到消息。
app/backend/cmd/holyarrs/ main.go starts the program; wiring.go builds the modules and joins them
app/backend/internal/<module>/ one flat folder per module
app/backend/internal/core/ plumbing every module may use
app/backend/tools/ dev-only programs
app/frontend/ the SvelteKit web app; embed.go bundles its build
app/frontend/src/routes/<page>/ thin pages that combine module parts
app/frontend/src/lib/<module>/ each module's web code
app/frontend/src/lib/ui/ parts used by 2 or more modules, and nothing else
app/frontend/src/lib/core/ server client, app state, helpers
app/tests/ end-to-end tests (Playwright)
deploy/ the Dockerfile and release scripts
docs/ guides and these pages

go.mod 放在仓库根部,因为 go:embed 够不到上级文件夹。

你想改 去这里找
资源怎么挑选 internal/mediafiles
某个下载器的客户端 internal/downloads,契约测试在 internal/downloads/conformance_test.go
某个通知渠道 internal/alerts
登录、用户、API 密钥 internal/accounts
首次运行的设置向导 internal/setup、app/frontend/src/routes/welcome
导入下载好的文件(解压、标签、匹配) internal/importer
媒体库文件夹、接管和重命名 internal/library
各行和各栏内容怎么挑、怎么排 internal/suggest
哪些功能模块是开着的 internal/core/parts
某个页面地址 app/frontend/src/routes/
某个迁移 internal/core/database/migrations/
Docker 镜像 deploy/Dockerfile

app/backend/tools/structurecheck 里的检查会在任何一条规则被破坏时让构建失败。运行它们的命令在测试里。

  • 分层顺序。 一个模块只能导入更低层的模块,而且只能导入它们的根包。同一层的模块互不导入。
  • 向上调用。 低层模块需要高层模块的东西时,由高层模块把普通数据传下来,或者由低层模块定义一个小接口,交给 wiring.go 填上。
  • SQL 不出门。 只有模块自己的 store*.go 文件里能写 SQL,而且只能操作自己的表。要读别的模块的行,就调用它的服务。
  • 共享表归 core。 settings、schedules、secrets、jobs 和 events 要通过 core 的辅助函数来访问。
  • 对外只有一个出口。 每个对外调用都走 core/outbound。
  • 暂未开放的功能要在 core/startup 注册一个开关。开关关着时,路由不存在,页面也会隐藏这个功能。
  • 不要杂物包。 不要 util、common、shared 或 helpers。

分层顺序见模块。

模块内部

每个后端模块都用同样的文件名。

文件 内容
routes.go API 路由,每条都带着它需要的权限
service.go 和各主题文件 供其他模块调用的逻辑
store.go、store_<topic>.go 操作模块自己那些表的全部 SQL
types.go 模块的记录

在 Web 这边,lib/<module>/ 里有 index.ts(其他模块可以用的东西)、它的 Svelte 组件和对应的测试;只有当它有自己的调用或状态时,才会有 api.ts 和 state.svelte.ts。

core 包

core 是底层管道。它不含任何产品规则,也不导入任何模块。

包 内容
core/database 打开并迁移两个 SQLite 文件、查询辅助函数、设置和事件的辅助函数、共享的行字段、历史记录裁剪
core/files 文件和文件夹的辅助函数、可用磁盘空间
core/releasename 从资源名里读出画质、发布组和集号
core/outbound 调用外部服务器的唯一出口,带地址检查
core/secrets 密钥存储和密钥轮换
core/logs 应用日志和崩溃记录
core/jobs 后台任务队列、计划,以及崩溃后会重启的循环
core/webserver 路由管道、URL 基础路径、压缩、实时推送
core/startup 运行身份用户、低内存模式、暂未开放功能的开关、内存上限、功能模块
core/parts 功能模块开关,每个模块在提供服务或运行之前都要先问它
core/model 共享类型,比如操作者和对象

core 必须碰模块数据时,由模块在 wiring.go 里向 core 注册一个钩子。密钥轮换就是这样做的。

数据
文件 内容
holyarrs.db 媒体库、请求、设置,以及其他所有重要的东西
holyarrs-events.db 历史记录和其他事件行。它会不断变大,裁剪时不会动主文件

迁移是带编号的 SQL 文件,放在 core/database/migrations/main 和 core/database/migrations/events 里。它们在启动时运行。

HolyArrs 是免费的。如果它帮你省了时间,欢迎在 GitHub 上点个 Star、赞助它或请我喝杯咖啡。