Pular para o conteúdo

Arquitetura

Especialista

Descubra onde o código fica e quais regras valem antes de mudar algo grande.

O HolyArrs é um único programa em Go com o app web embutido. Ele serve o app web e uma API JSON na porta 6262, e guarda os dados em 2 arquivos SQLite na pasta de configuração. Ele chama Gerenciadores de downloads, Fontes (pelo Jackett ou pelo Prowlarr), servidores de mídia, canais de alerta e o servidor de metadados do HolyArrs.

Acompanhe um pedido. Alguém pede um filme no Explorar.

  1. requests registra o pedido.
  2. Depois da aprovação, movies pede Lançamentos a sources.
  3. As regras de escolha em mediafiles dão pontos a cada um.
  4. downloads envia o melhor para o Gerenciador de downloads.
  5. Quando o download termina, mediafiles importa o arquivo.
  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 alcança uma pasta pai.

Onde encontrar cada coisa

Link para Onde encontrar cada coisa
Você quer mudar Procure em
Como um Lançamento é escolhido internal/mediafiles
Um cliente de Gerenciador de downloads internal/downloads, testes de contrato em internal/downloads/conformance_test.go
Um canal de alerta internal/alerts
Login, usuários, chaves de API internal/accounts
O assistente de primeira execução internal/setup, app/frontend/src/routes/welcome
A importação de um arquivo pronto (descompactar, tags, correspondência) internal/importer
Pastas da Biblioteca, adoção e renomeação internal/library
Como as fileiras e prateleiras são escolhidas e ordenadas internal/suggest
Quais partes do 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. Execute as verificações com a linha que está em Testes.

  • Ordem das camadas. Um módulo importa só módulos de uma camada mais baixa, e só o pacote raiz deles. Módulos da mesma camada nunca importam um ao outro.
  • Chamar para cima. Quando um módulo mais baixo precisa de algo de um mais alto, o mais alto passa dados simples para baixo, ou o mais baixo define uma interface pequena que o wiring.go preenche.
  • O SQL fica em casa. Só os arquivos store*.go do próprio módulo têm SQL, e só sobre as tabelas do próprio módulo. Para ler as linhas de outro módulo, chame o serviço dele.
  • As tabelas compartilhadas são do core. Acesse settings, schedules, secrets, jobs e events pelos auxiliares do core.
  • Uma saída só. Toda chamada externa passa por core/outbound.
  • Recursos retidos registram uma chave em core/startup. Enquanto a chave está desativada, a rota não existe e a página esconde o recurso.
  • Nada de pacotes saco de gatos. Nada de util, common, shared ou helpers.

A ordem das camadas está em Módulos.

Dentro de um módulo

Todo módulo do backend usa os mesmos nomes de arquivo.

Arquivo Contém
routes.go As rotas da API, cada uma com a permissão que exige
service.go e arquivos por assunto 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 registros do módulo

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

Pacotes do core

O core é encanamento. Ele não tem regras do produto e não importa nenhum módulo.

Pacote Contém
core/database Abertura e migração dos dois arquivos SQLite, auxiliares de consulta, auxiliares de configurações e eventos, campos de linha compartilhados, corte do histórico
core/files Auxiliares de arquivos 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 O único jeito de chamar servidores externos, com verificação de endereços
core/secrets O cofre de chaves e a rotação de chaves
core/logs O log do app e as notas de falha
core/jobs A fila de tarefas, os agendamentos e os loops que reiniciam depois de uma falha
core/webserver Encanamento do roteador, URL base, compressão, envio ao vivo
core/startup Usuário de execução, modo de pouca memória, chaves de recursos retidos, limite de memória, partes
core/parts As chaves de parte que todo módulo consulta antes de servir ou executar
core/model Tipos compartilhados, como atores e assuntos

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

Dados
Arquivo Contém
holyarrs.db A Biblioteca, os pedidos, as configurações e tudo o mais que importa
holyarrs-events.db O Histórico e outras linhas de eventos. Ele cresce e é cortado sem mexer no arquivo principal

As migrações são arquivos SQL numerados em core/database/migrations/main e core/database/migrations/events. Elas são executadas na inicialização.

O HolyArrs é gratuito. Se ele poupou seu tempo, dê uma estrela no GitHub, patrocine o projeto ou me pague um café.