Pular para o conteúdo

Arquitetura

Especialista

Descobre onde está o código e que regras se aplicam antes de mudares algo grande.

O HolyArrs é um único programa em Go com a app web incluída. Serve a app web e uma API JSON na porta 6262 e guarda os dados em 2 ficheiros SQLite na pasta de configuração. Liga-se a gestores de transferências, a Fontes (através do Jackett ou do Prowlarr), a servidores multimédia, a canais de avisos e ao servidor de metadados do HolyArrs.

Segue um pedido. Alguém pede um filme em Explorar.

  1. requests regista o pedido.
  2. Depois da aprovação, movies pede lançamentos a sources.
  3. As regras de escolha em mediafiles pontuam-nos.
  4. downloads envia o melhor para o gestor de transferências.
  5. Quando acaba, mediafiles importa o ficheiro.
  6. mediaservers e alerts são avisados.
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

O go.mod fica na raiz do repositório porque o go:embed não consegue chegar a uma pasta acima.

Queres mudar Procura em
Como se escolhe um lançamento internal/mediafiles
Um cliente de gestor de transferências internal/downloads, testes de contrato em internal/downloads/conformance_test.go
Um canal de avisos internal/alerts
Início de sessão, utilizadores, chaves de API internal/accounts
O assistente da primeira execução internal/setup, app/frontend/src/routes/welcome
Importar um ficheiro terminado (descomprimir, etiquetas, correspondência) internal/importer
Pastas da Biblioteca, adoção e mudança de nomes internal/library
Como as linhas e prateleiras são escolhidas e ordenadas internal/suggest
Que partes da app estão ativas internal/core/parts
O endereço de uma página app/frontend/src/routes/
Uma migração internal/core/database/migrations/
A imagem Docker deploy/Dockerfile

As verificações em app/backend/tools/structurecheck fazem a compilação falhar quando uma regra é quebrada. Executa-as com a linha de Testes.

  • Ordem das camadas. Um módulo só importa módulos de uma camada inferior, e só o seu pacote de raiz. Módulos da mesma camada nunca se importam uns aos outros.
  • Chamar para cima. Quando um módulo inferior precisa de algo de um superior, o superior passa dados simples para baixo, ou o inferior define uma interface pequena que o wiring.go preenche.
  • O SQL fica em casa. Só os ficheiros store*.go de um módulo têm SQL, e só sobre as suas próprias tabelas. Para ler linhas de outro módulo, chama o serviço dele.
  • As tabelas partilhadas pertencem ao core. Acede a settings, schedules, secrets, jobs e events através dos auxiliares do core.
  • Uma só saída. Todas as chamadas para fora passam por core/outbound.
  • As funcionalidades retidas registam um interruptor em core/startup. Enquanto estiver desativado, a rota não existe e a página esconde a funcionalidade.
  • Sem pacotes “saco de gatos”. Nada de util, common, shared ou helpers.

A ordem das camadas está em Módulos.

Dentro de um módulo

Todos os módulos do backend usam os mesmos nomes de ficheiros.

Ficheiro Contém
routes.go Rotas da API, cada uma com a permissão de que precisa
service.go e ficheiros por tema A lógica que outros módulos chamam
store.go, store_<topic>.go Todo o SQL das tabelas do próprio módulo
types.go Os registos do módulo

Do lado da web, lib/<module>/ tem o index.ts (o que outros módulos podem usar), as suas partes Svelte e respetivos testes, e api.ts e state.svelte.ts só quando tem chamadas ou estado próprios.

Pacotes do core

O core é a canalização. Não tem regras de produto e não importa nenhum módulo.

Pacote Contém
core/database Abrir e migrar os dois ficheiros SQLite, auxiliares de consultas, de definições e de eventos, campos de linha partilhados, limpeza do histórico
core/files Auxiliares de ficheiros e pastas, espaço livre em disco
core/releasename Qualidade, grupo e números de episódio a partir do nome de um lançamento
core/outbound A única forma de chamar servidores externos, com verificação de endereços
core/secrets O armazém de chaves e a rotação de chaves
core/logs O registo da app e as notas de falha
core/jobs A fila de tarefas, os agendamentos e os ciclos que recomeçam depois de uma falha
core/webserver Encaminhamento, URL base, compressão, envio em direto
core/startup Utilizador de execução, modo de pouca memória, interruptores de funcionalidades retidas, limite de memória, partes
core/parts Os interruptores das partes que cada módulo consulta antes de servir ou executar
core/model Tipos partilhados, como atores e sujeitos

Quando o core tem de mexer em dados de um módulo, o módulo regista um gancho no core em wiring.go. A rotação de chaves funciona assim.

Dados
Ficheiro Contém
holyarrs.db A Biblioteca, os pedidos, as definições e tudo o resto que importa
holyarrs-events.db O histórico e outras linhas de eventos. Cresce e é aparado sem tocar no ficheiro principal

As migrações são ficheiros SQL numerados em core/database/migrations/main e core/database/migrations/events. Correm no arranque.

O HolyArrs é gratuito. Se te poupou tempo, dá-lhe uma estrela no GitHub, patrocina-o ou oferece-me um café.