Percebi que a tarefa rake assets:precompile exige uma conexão com o banco de dados: isso significa que a tarefa só pode ser executada em “tempo de execução” (após a implantação), e não em “tempo de compilação” (durante a construção da imagem do contêiner). Como a tarefa é muito custosa em termos de tempo de execução, isso pode ser incômodo.
Não sendo desenvolvedor Ruby/Rails, fiz algumas pesquisas e descobri que esse comportamento poderia ser desativado até o Rails 4 e, depois disso, os desenvolvedores têm recorrido a algumas soluções alternativas (conexão nula ao banco de dados). A última, claro, exige conhecimento profundo da aplicação, para evitar quebrar algo.
Ao procurar uma solução melhor, encontrei este commit, que parece ter um espírito semelhante. Então, minhas perguntas são:
os desenvolvedores já estão trabalhando no assunto, ou há razões técnicas que impedem que isso seja feito?
se algumas partes da tarefa realmente exigirem a conexão com o banco de dados, seria viável dividir a tarefa em duas (ou mais), de modo que parte do trabalho (por exemplo, compilar localizações, minificar JS e CSS) possa ser feito em tempo de compilação?
existe alguma solução alternativa conhecida no momento (por exemplo, “banco de dados nulo”, como mencionado acima)?
Armazenamos os temas no banco de dados (eles são editados na interface de administração), então o CSS está dentro do PostgreSQL. Portanto, você precisa da conexão com o banco de dados no momento da compilação para poder pré-compilá-los.
Seria viável implementar a compilação de localizações separadamente (para ser executada no momento da compilação)?
Além disso, consigo imaginar que alguns ambientes (no meu caso, pelo menos) podem não querer permitir a alteração de temas: seria possível fornecer um armazenamento alternativo para o CSS nesses casos?
Discutimos a ideia de um interruptor que desativaria toda a interface de personalização, permitindo que os arquivos CSS fossem compilados no momento da construção e carregados no armazenamento de objetos durante o build (ou seja, da mesma forma que o núcleo JS e os plugins).
No entanto, esse é um caso muito específico, que só atrairia implantações de nível empresarial, sem oferecer qualquer valor para 99% das comunidades na web. Portanto, isso não está em nosso roteiro, e seria muito difícil justificar o trabalho nisso em vez de desenvolver novos recursos ou melhorar o desempenho.
Pode nos contar mais sobre seu ambiente e caso de uso?
Bom saber que a ideia já foi discutida. Entendo que o volume de trabalho para a mudança provavelmente seja grande demais para ser justificável.
No meu caso, o Discourse estará associado a um site pré-existente, então haverá um tema personalizado fixo para combinar com o do site: não faria sentido alterá-lo dinamicamente.
Ah, bem, quando construo a imagem, trabalho no meu laptop de desenvolvimento. A imagem é então enviada para um repositório, e o sistema final (VPS no DigitalOcean) a busca de lá.
O banco de dados fica em um volume no VPS, então não pode ser atualizado no meu laptop: isso exigiria que eu parasse o Discourse, sincronizasse o banco de dados com meu laptop, construísse e enviasse a imagem e, finalmente, reiniciasse o Discourse…
Então você está executando o banco de dados e o aplicativo todos dentro de um único droplet?
Nesse caso, seguir nosso guia de instalação oficial, que resulta em um droplet com aplicativo e banco de dados no mesmo droplet, fornecerá um site totalmente funcional, que pode ser atualizado pela interface web e, opcionalmente, pela linha de comando com uma reconstrução completa da imagem.
Se com isso você quer dizer “diretamente no host”, então não. Eles estão rodando em um container, especificamente um container podman. Idealmente, eu dividiria o container em vários (um para o Discourse, um para o Postgres, um para o Redis…), mas isso se conecta com a questão que estamos discutindo, então ainda não tenho certeza sobre o caminho correto a seguir.
Parece inseguro para mim. Geralmente, eu testo os containers no meu ambiente de desenvolvimento antes de implantar em produção. Além disso, idealmente, os containers deveriam ser somente leitura.
Você pode separar esses containers e, em seguida, executar o processo de inicialização da imagem em outra Droplet de curta duração. Como as Droplets são cobradas por hora, isso será barato. Você até pode aproveitar a rede privada das Droplets entre o host do container de banco de dados e o host do container de “build”.
Hehe, obrigado pela ideia, mas isso começa a ficar complicado. Além disso, não resolverá o problema, pois ainda precisaremos interromper o Discourse e aguardar o processo de inicialização, ou poderemos ter dados inconsistentes.
Parece que teremos que conviver com um tempo de inatividade prolongado (5 a 6 minutos para migração e pré-compilação) durante a atualização. Ainda assim, eu apreciaria se vocês pudessem manter um issue de baixa prioridade no rastreador, talvez com um link para este tópico.
Deveria ser apenas “alguns segundos” em vez de 5-6 minutos, mas você precisará de contêineres de dados e web dedicados. Depende do que você deseja priorizar.
Além disso, conforme os benchmarks, a reconstrução em um servidor rápido deve levar cerca de 3 minutos.
Bom saber, obrigado. Neste caso, vou definitivamente separar os containers, o que é uma arquitetura melhor de qualquer forma.
No entanto, não consigo ver como isso faz diferença? Se não me engano, todos os containers compartilham todos os CPUs do host (a menos que configurado de outra forma), então os processos devem ser executados em paralelo em ambos os casos. Estou perdendo algo?
Seu antigo contêiner continuará em execução enquanto o novo estiver sendo inicializado. Em seguida, você poderá desligar rapidamente o antigo e iniciar o novo, reduzindo assim o tempo de inatividade.