Estive coçando minha cabeça com essa por quase duas semanas. Eu tenho um servidor Ubuntu 14.04 com o rbenv instalado executando vários sites diferentes do Rails, alguns deles em versões mais antigas do Rails, outros na versão mais recente.
Eu tenho 2 sites em particular que exigem uma versão diferente do puma_worker_killer, 1 requer 0.1.0 e o outro 0.1.1. Ambos os sites usam o Ruby 2.5.3.
Quando inicio o servidor RAILS_ENV=dev3 bundle exec pumactl -F ./config/puma.rb start
, recebo o seguinte erro nos logs e o site trava:
You have already activated puma_worker_killer 0.1.1, but your Gemfile requires puma_worker_killer 0.1.0. Prepending `bundle exec` to your command may solve this. (Gem::LoadError)
No começo, pensei que poderia ter havido um problema com o rbenv, pois eu tinha as gemas instaladas em ~ / .gem, em vez de em ~ / .rbenv, então coloquei todos os rubis em ~ / .gem e os instalei recentemente no correto pasta rbenv com bundle install
e ainda recebo o mesmo problema.
Agora, neste momento, quero esclarecer que fiz uma extensa pesquisa on-line sobre esse assunto e sei que posso fazer muitas coisas para resolver isso.
Eu sei que posso apenas mudar a versão e bundle update puma_worker_killer
.
Também sei que posso remover a versão mais recente executando gem uninstall puma_worker_killer
e escolhendo 0.1.1, mas isso significaria que as dependências no outro site não seriam atendidas.
Fiz algumas investigações no código-fonte do bundler e posso ver que ele é causado pela seguinte linha de código:
return if activated_spec.version == spec.version
Quando executado no contexto do bundler usando bundle exec
tanto o activated_spec
e spec
corresponder, o que significa que o seguinte código nesse método ( check_for_activated_spec!
) não é executado. Por alguma razão, ao executar o comando acima para iniciar o servidor, activated_spec
(a gema ativada) é a versão mais recente (0.1.1) e não a listada no Gemfile (0.1.0), o que significa que não retorna e lança o erro acima.
Também devo mencionar que também parece haver o mesmo problema com o get_process_mem, que é uma das dependências do puma_worker_killer. Ele reclama de já ativar o 0.2.5, mas meu Gemfile quer o 0.2.4:
You have already activated get_process_mem 0.2.5, but your Gemfile requires get_process_mem 0.2.4. Prepending `bundle exec` to your command may solve this. (Gem::LoadError)
Entendo que o empacotador deve carregar a versão listada no Gemfile ao usá-lo bundle exec
para combater esse problema de ter várias versões da mesma joia.
Eu sei que também poderia criar um gemset separado (que pode ser feito com o rbenv aparentemente) que possui diferentes versões do puma_worker_killer e executar rbenv local 2.5.3-pwk0.1.0
ou, rbenv local 2.5.3-pwk0.1.1
dependendo da versão que eu quero, dentro do projeto, mas isso parece um exagero para o que eu quero alcançar.
Nesse ritmo, sou tentado a atualizar todos os sites com a versão mais recente do puma_worker_killer e do get_process_mem e depois bloqueá-los e remover todas as versões mais antigas do servidor, mas acho que não preciso fazer isso.
Alguém sabe o que está acontecendo aqui ou se estou fazendo algo flagrantemente errado?
Abaixo está o código que eu uso para usar o puma_worker_killer na minha configuração do puma.
before_fork do
require 'puma_worker_killer'
PumaWorkerKiller.config do |config|
config.ram = 1024 # mb
config.frequency = 5 # seconds
config.percent_usage = 0.98
config.rolling_restart_frequency = 12 * 3600 # 12 hours in seconds
end
PumaWorkerKiller.start
end
bundle update puma_worker_killer
não é realmente uma vez que só vai usar a nova versão do puma_worker_killer que está instalado no servidorRespostas:
O que está acontecendo aqui é basicamente que você tem várias versões da gema em seu sistema.
Na maioria das vezes, não causava problemas, porque
bundle exec
carregava dinamicamente as versões necessárias para o seu aplicativo.Em alguns casos, as gemas terão arquivos binários incluídos. Nesse caso
bundle exec
, não ajudará porque você pode ter apenas uma versão vinculada em um momento.Basicamente, se você quiser chamar o binário por alias, precisará usar o gemset separado para cada aplicativo.
Se você deseja manter todas as gemas em um só lugar, pode chamar arquivos binários diretamente.
No seu caso, será:
A
_<version>_
construção permite especificar a versão do arquivo binário que você deseja executar.Você também pode criar seu binário personalizado, como
fake_pumactl
dentro do projeto, que verificaráGemfile.lock
e fará proxy automaticamente da sua chamada para a biblioteca e especificará a versão automaticamente para você. Outra maneira é analisar a versão da gema pelo shell script e colocá-lo em vez de_<version>_
na sua chamada.Aqui está o breve exemplo
puma_version
A variável pode ser definida a partir do resultado de um comando bash, do qual extrairá a versão gemGemfile.lock
.fonte
RAILS_ENV=dev3 bundle exec pumactl _4.1.0_ -F ./config/puma.rb start
e ele inicia a 3.7.0 e não a 4.1.0 (Version 3.7.0 (ruby 2.5.3-p105), codename: Snowy Sagebrush
)You can create your custom binary as well, like fake_pumactl inside the project which will check the Gemfile.lock and automatically proxy your call to the library and specify version automatically for you.
➜ app_root git:(develop) ✗ gem install puma -v 3.12.0 Building native extensions. This could take a while... Successfully installed puma-3.12.0 Done installing documentation for puma after 1 seconds 1 gem installed ➜ app_root git:(develop) ✗ pumactl _3.12.0_ -v 3.7.0
Preciso descobrir por que isso acontece, mas você realmente respondeu minha pergunta, então obrigado e vou marcá-lo como respondidopumactl ${puma_version} -v
com${pumactl_path} -v
bem, deve funcionar dentro do diretório projeto ondepumactl_path
será definido como caminho para uma forlder dentro gem binário. TalvezGemfile.lock
influencie o resultado do seu comando porque ele contém uma versão mais antiga.