Starting multiple DelayedJob workers w/ specific queues via Capistrano tasks - ruby-on-rails

I'm looking into using queues with delayed_job. I've found this page which outlines various ways of starting workers, however I'd like to keep my currently Capistrano method:
set :delayed_job_args, "-n 2 -p ecv2.production"
after "deploy:start", "delayed_job:start"
...
I was wondering how I could modify the delayed_job_args to handle spawning 1 worker with a specific queue, and 1 worker for every other job. So far, all I have is overriding each task like so:
namespace :delayed_job do
task :restart, :roles => :app do
run "cd #{current_path}; RAILS_ENV=#{rails_env} script/delayed_job -p ecv2.production --queue=export restart"
run "cd #{current_path}; RAILS_ENV=#{rails_env} script/delayed_job -p ecv2.production restart"
end
end
... But that's no fun. Any suggestions?

I split my jobs into two queues with one worker isolated to each queue with this setup in my deploy.rb file:
namespace :delayed_job do
task :start, roles: :app do
run "cd #{current_path}; #{rails_env} bundle exec script/delayed_job -i queue_one --queue=one start"
run "cd #{current_path}; #{rails_env} bundle exec script/delayed_job -i queue_two --queue=two start"
end
task :stop, roles: :app do
run "cd #{current_path}; #{rails_env} bundle exec script/delayed_job -i queue_one --queue=one stop"
run "cd #{current_path}; #{rails_env} bundle exec script/delayed_job -i queue_two --queue=two stop"
end
task :restart, roles: :app do
run "cd #{current_path}; #{rails_env} bundle exec script/delayed_job -i queue_one --queue=one restart"
run "cd #{current_path}; #{rails_env} bundle exec script/delayed_job -i queue_two --queue=two restart"
end
end
The -i name part of the command is very important. That's the part that allows multiple delayed_job instances to run.
If you want to add workers to specific queues, then you would expand them out like this (where I have two workers exclusively on queue one, and one worker exclusively on queue two):
namespace :delayed_job do
task :start, roles: :app do
run "cd #{current_path}; #{rails_env} bundle exec script/delayed_job -i one1 --queue=one start"
run "cd #{current_path}; #{rails_env} bundle exec script/delayed_job -i one2 --queue=one start"
run "cd #{current_path}; #{rails_env} bundle exec script/delayed_job -i two --queue=two start"
end
task :stop, roles: :app do
run "cd #{current_path}; #{rails_env} bundle exec script/delayed_job -i one1 stop"
run "cd #{current_path}; #{rails_env} bundle exec script/delayed_job -i one2 stop"
run "cd #{current_path}; #{rails_env} bundle exec script/delayed_job -i two stop"
end
task :restart, roles: :app do
run "cd #{current_path}; #{rails_env} bundle exec script/delayed_job -i one1 --queue=one restart"
run "cd #{current_path}; #{rails_env} bundle exec script/delayed_job -i one2 --queue=one restart"
run "cd #{current_path}; #{rails_env} bundle exec script/delayed_job -i two --queue=two restart"
end
end

After a bit of messing around, the trick I found was to revert to the 'set :delayed_job_args' and use --queues= (plural) instead of --queue= (singular). Hope this helps anyone else who runs into the same issue.
set :delayed_job_args, "-n 2 -p ecv2.production --queues=cache,export"
UPDATE: What I'm using now...
after "deploy:stop", "delayed_job:stop"
after "deploy:start", "delayed_job:start"
after "deploy:restart", "delayed_job:restart"
namespace :delayed_job do
# See 'man nice' for details, default priority is 10 and 15 is a bit lower
task :start, :roles => :app do
run "cd #{current_path}; #{rails_env} nice -n 15 ruby script/delayed_job -n 1 -p yourapp.#{application} start"
end
task :restart, :roles => :app do
stop
start
end
end

Related

Capistrano bash: bundle: command not found even has been installed

Hi guys i have problem to deploy my rails app to production server. Actually i have install bundle in server via gem install bundler. Unfortunately when i typed cap production deploy it becomes like this:
** [out :: server url] bash: bundle: command not found
command finished in 772ms
*** [deploy:update_code] rolling back
* executing "rm -rf /home/deployer/crawler/releases/20180326063414; true"
servers: ["server url"]
[server url] executing command
command finished in 833ms
failed: "rvm_path=$HOME/.rvm/ $HOME/.rvm/bin/rvm-shell 'ruby-2.2.1' -c 'cd /home/deployer/crawler/releases/20180326063414 && bundle install --gemfile /home/deployer/crawler/releases/20180326063414/Gemfile --path /home/deployer/crawler/shared/bundle --deployment --quiet --without development test'" on server url
it says bash: bundle: command not found. I typed bundle --version the output is:
Bundler version 1.16.1
here is my gemfile
group :development do
gem 'capistrano', '~>2.15.4'
gem 'rvm-capistrano', '1.4.1', require: false
gem 'invoker'
gem 'regularity', require: nil
gem 'pry-rails'
end
and here is my deploy.rb:
require "bundler/capistrano"
require "rvm/capistrano"
require 'capistrano/ext/multistage'
require 'rollbar/capistrano'
#set :rollbar_token, '3dc5b293a0c74c3e8b98ab26f07bea74'
set :rollbar_token, 'de21e333f1d5469ea521c2ef3a29bd3d'
set :application, "crawler"
# set :repository, "git#bitbucket.org:terbang-ventures/linkedin-scraper.git"
set :repository, "git#bitbucket.org:terbang-ventures/linkedin-scraper.git"
set :rails_env, "production"
set :branch, "master"
set :scm, :git
set :default_shell, '/bin/bash -l'
# set :whenever_environment, defer { stage }
# require "whenever/capistrano"
set :stages, %w(production staging)
set :user, 'deployer'
set :rvm_type, :user
set :rvm_ruby_string, 'ruby-2.2.1'
set :rvm_binary, '~/.rvm/bin/rvm'
$:.unshift(File.expand_path('./lib', ENV['rvm_path']))
set :deploy_to, "/home/#{user}/#{application}"
set :use_sudo, false
set :deploy_via, :remote_cache
default_run_options[:pty] = true
ssh_options[:forward_agent] = true
namespace :deploy do
desc 'Load environment variables'
task :load_env_vars do
run "ln -s /home/#{user}/env.yml #{current_release}/config/env.yml"
end
desc "Migrate DB1"
task :migrate_db1 do
# rake db:migrate_db1 RAILS_ENV=staging
run "cd #{current_path} && bundle exec rake db:migrate_db1 RAILS_ENV=#{rails_env}"
end
desc 'Re-establish mongoid.yml'
task :set_database_symlink do
run "ln -s /home/#{user}/mongoid.yml #{current_release}/config/mongoid.yml"
end
desc 'Re-establish database.yml'
task :set_database_symlink_active_record do
run "ln -s /home/#{user}/database.yml #{current_release}/config/database.yml"
end
desc 'run bundle install'
task :install_bundle do
run "cd #{current_path} && bundle install"
end
task :restart, :roles => :app, :except => { :no_release => true } do
run "ps axf | grep puma | grep -v grep | awk '{print \"kill -9 \" $1}' | sh"
run "cd #{current_path} && bundle exec puma -e #{rails_env} -p 9292 -d"
run "cd #{current_path} && bundle exec puma -e #{rails_env} -p 9293 -d"
end
task :stop, :roles => :app, :except => { :no_release => true } do
run "ps axf | grep puma | grep -v grep | awk '{print \"kill -9 \" $1}' | sh"
end
task :start, :roles => :app, :except => { :no_release => true } do
run "cd #{current_path} && bundle exec puma -e #{rails_env} -p 9292 -d"
run "cd #{current_path} && bundle exec puma -e #{rails_env} -p 9293 -d"
end
end
namespace :searchkick do
# reindex
namespace :reindex do
# Reindex Contact
task :contact, except: {no_release: true} do
run "cd #{current_path} && bundle exec rake searchkick:reindex CLASS=Contact RAILS_ENV=#{rails_env}"
end
# Reindex Contact
task :company, except: {no_release: true} do
run "cd #{current_path} && bundle exec rake searchkick:reindex CLASS=Company RAILS_ENV=#{rails_env}"
end
task :user, except: {no_release: true} do
run "cd #{current_path} && bundle exec rake searchkick:reindex CLASS=User RAILS_ENV=#{rails_env}"
end
task :all, except: {no_release: true} do
run "cd #{current_path} && bundle exec rake searchkick:reindex:all RAILS_ENV=#{rails_env}"
end
end
end
namespace :importer do
task :department, roles: :app, except: {no_release: true} do
run "cd #{current_path} && bundle exec rake importer:import_department RAILS_ENV=#{rails_env}"
end
task :staff_level, roles: :app, except: {no_release: true} do
run "cd #{current_path} && bundle exec rake importer:import_staff_level RAILS_ENV=#{rails_env}"
end
task :email_format, roles: :app, except: {no_release: true} do
run "cd #{current_path} && bundle exec rake importer:import_email_format RAILS_ENV=#{rails_env}"
end
task :combined_emails, roles: :app, except: {no_release: true} do
run "cd #{current_path} && bundle exec rake importer:import_combined_emails RAILS_ENV=#{rails_env}"
end
task :late_address, roles: :app, except: {no_release: true} do
run "cd #{current_path} && bundle exec rake importer:import_late_address RAILS_ENV=#{rails_env}"
end
end
namespace :rails do
desc "Remote console"
task :console, roles: :app, except: { no_release: true } do
run_interactively "bundle exec rails c -e #{rails_env}"
end
desc "Remote dbconsole"
task :dbconsole, roles: :app, except: { no_release: true } do
run_interactively "bundle exec rails dbconsole -e #{rails_env}"
end
# Short aliases
task :c, roles: :app do
console
end
task :dbc, roles: :app do
dbconsole
end
desc "Monitor log"
task :log, roles: :app, except: { no_release: true } do
run_interactively "tail -f log/#{rails_env}.log"
end
def run_interactively(command)
server ||= find_servers_for_task(current_task).first
puts " running `#{command}` as #{user}##{server}"
exec %Q(ssh #{user}##{server} -t "bash --login -c 'cd #{current_path} && #{command}'")
end
end
after "deploy", "deploy:cleanup"
after "deploy", "deploy:migrate"
after "deploy:migrate", "deploy:migrate_db1"
after "deploy:start", "sidekiq:start"
after "deploy", "sidekiq:restart"
before "deploy:assets:precompile", "deploy:load_env_vars"
before "deploy:assets:precompile", "deploy:set_database_symlink"
before "deploy:assets:precompile", "deploy:set_database_symlink_active_record"
before "deploy:assets:precompile", "deploy:assets:clean"
before "deploy:migrate", "deploy:install_bundle"
My question is, why that capistrano still asking my bundle command not found if i trace it failed in rvm_path=$HOME/.rvm/ $HOME/.rvm/bin/rvm-shell 'ruby-2.2.1' -c 'cd /home/deployer/crawler/releases/20180326065919 && bundle install --gemfile /home/deployer/crawler/releases/20180326065919/Gemfile --path /home/deployer/crawler/shared/bundle --deployment --quiet --without development test'?

Why I'm getting "undefined local variable or method `rails_env'"?

I'm getting undefined local variable or method 'rails_env'when doing
execute "cd #{current_path} && RAILS_ENV=#{rails_env} bundle exec rake sunspot:solr:stop"
I'm not a big capistrano or rails expert.
On deploy.rb I have
namespace :solr do
desc "start solr"
task :start do
on roles(:app) do
execute "cd #{current_path} && RAILS_ENV=#{rails_env} bundle exec rake sunspot:solr:start"
end
end
desc "stop solr"
task :stop do
on roles(:app) do
execute "cd #{current_path} && RAILS_ENV=#{rails_env} bundle exec rake sunspot:solr:stop"
end
end
desc "reindex the whole database"
task :reindex do
on roles(:app) do
invoke 'solr:stop'
execute "rm -rf #{shared_path}/solr/data/*"
invoke 'solr:start'
execute "cd #{current_path} && RAILS_ENV=#{rails_env} d"
end
end
desc "Symlink in-progress deployment to a shared Solr index"
task :symlink do
on roles(:app) do
execute "ln -s #{shared_path}/solr/data/ #{release_path}/solr/data"
execute "ln -s #{shared_path}/solr/pids/ #{release_path}/solr/pids"
invoke 'solr:reindex'
end
end
end
after "deploy:finishing", "solr:symlink"
And on deploy/staging.rb I have
set :rails_env, :staging
What's missed?
You should use fetch method. So, instead of rails_env use:
fetch(:rails_env)
Here (or here) is more details.
Try replacing rails_env with Rails.env

Capistrano deployment behaviour

I have this deploy.rb
after 'deploy:update_code', 'deploy:symlink_db', 'deploy:symlink_email'
after 'deploy:setup', 'setup:create_db_configuration', 'setup:create_email_configuration'
namespace :deploy do
desc "Symlinks the email.yml"
task :symlink_email, :roles => :app do
puts "##Sybolic Link the email.yml"
run "ln -nfs #{deploy_to}/shared/config/email.yml #{release_path}/config/email.yml"
end
desc "Symlinks the database.yml"
task :symlink_db, :roles => :app do
puts "##Sybolic Link the database.yml"
run "ln -nfs #{deploy_to}/shared/config/database.yml #{release_path}/config/database.yml"
end
But when I deploy, after the deploy:update_code it starts with
2013-07-27 03:30:30 executing `deploy:assets:symlink'
then
2013-07-27 03:30:32 executing `deploy:assets:precompile'
And when execution
executing "cd -- /home/ubuntu/deployments/saleshub/releases/20130727013023 && RAILS_ENV=production RAILS_GROUPS=assets rake assets:precompile"
It fails, because the symbolic links were not created yet. How do I make sure the my tasks to create the symlinks before compiling the assets?
before 'deploy:assets:precompile', 'deploy:symlink_db', 'deploy:symlink_email'

Rails 2 + Delayed_job 2.0.7: Best way to automate the worker to start jobs?

I'm researching and finding it hard to find a mainstream way to start the worker for the delayed_job gem. So far, I have one solution to use Capistrano:
# add this to config/deploy.rb
namespace :delayed_job do
desc "Start delayed_job process"
task :start, :roles => :app do
run "cd #{current_path}; script/delayed_job start #{rails_env}"
end
desc "Stop delayed_job process"
task :stop, :roles => :app do
run "cd #{current_path}; script/delayed_job stop #{rails_env}"
end
desc "Restart delayed_job process"
task :restart, :roles => :app do
run "cd #{current_path}; script/delayed_job restart #{rails_env}"
end
end
after "deploy:start", "delayed_job:start"
after "deploy:stop", "delayed_job:stop"
after "deploy:restart", "delayed_job:restart"
but apparently there can be some cases where the Apache user is diferent from the Rails app user which will cause issues? Is there a better way to automate the worker process so that I don't have to sit at my comp and type
$ RAILS_ENV=production script/delayed_job start
$ RAILS_ENV=production script/delayed_job stop
all day in the console?
I created a rake task to run " rake:jobs workoff " once daily. You can set as often as you need. I used heroku scheduler.

How to just start 1 production Resque worker from Capistrano?

I've got Redis/Resque installed but I'm having a hard time starting/restarting it from Capistrano when I deploy.
My needs are fairly simple: I only have 1 queue, only need 1 worker, and I'm not using monit or god.
Based on this blog post, my deploy.rb has this:
namespace :deploy do
task :start do ; end
task :stop do ; end
task :restart, :roles => :app, :except => { :no_release => true } do
run "#{try_sudo} touch #{File.join(current_path,'tmp','restart.txt')}"
end
task :restart_resque do
pid_file = "#{shared_path}/pids/resque.pid"
run "test -f #{pid_file} && cd #{current_path} && kill -s QUIT `cat #{pid_file}` || rm -f #{pid_file}"
run "cd #{current_path}; RAILS_ENV=production QUEUE='*' VERBOSE=1 nohup rake environment resque:work& > #{shared_path}/log/resque.log && echo $! > #{pid_file}"
end
end
after 'deploy:restart', 'deploy:restart_resque'
My resque.rake file (based on the Railscast) has:
require "resque/tasks"
task "resque:setup" => :environment
When I cap deploy, everything seems to work but there are no workers running when I look at resque-web ...
I suggest you look at this StackOverflow question and this gist for quite a few suggestions.

Resources