Delayed Job Capistrano task without restarting each time - ruby-on-rails

How is this possible?
I am currently using Capistrano recipe that comes with delayed_job
This is what I have:
# Delayed Job recipes
require "delayed/recipes"
set :rails_env, "production" # added for delayed job
after "deploy:stop", "delayed_job:stop"
after "deploy:start", "delayed_job:start"
after "deploy:restart", "delayed_job:restart"
I don't understand very well Capistrano phases, maybe solution is to set right task to right phase.
 Update
Every time I deploy I get
executing `delayed_job:restart'
Is this really needed? Is there a way to restart delayed_job just when needed? or is it always needed?

I'm also not sure what you're looking for but maybe a simple
cap delayed_job:stop
from the command line will do? You can see all available tasks at
cap -T
UPDATE
I would argue that it is a best practice to restart your Delayed Job workers every time you deploy. In the end, the workers execute your code, and that tends to change between deploys. Now, if the code your workers run rarely changes (that includes the rails boot process, environment files, initializers, settings, models that you use, etc.) and you want to take care of this yourself, then simply remove the hooks such as
after "deploy:stop", "delayed_job:stop"
from the deploy.rb and you're fine: the dj tasks will still be at your disposal, but they will not be triggered during deploy.

Related

How to make sure resque background jobs are always up?

I use ActiveJob with a resque back-end and use capistrano-resque to (re)start my work processes on deploy.
What I have been strugling with is making sure those processes are always up. Can and could such a process crash? Should I put safeguards in making sure that my background jobs always get picked up by a worker?
I have searched far and wide but have not found any standard solution to this.
I am using god with resque. Here's an example script for it.
Capistrano
desc "Restart resque workers"
task :restart_workers, roles: :resque do
run "sudo god restart resque-production"
end
after 'deploy:restart', 'deploy:restart_workers'
where resque-production is the w.name from the script example.

Capistrano deploy one server at a time

I am using capistrano for our RAILS deployment. We want to deploy to one server first, and after deployment is finished on the first server, then we want to start deployment on second server. We do not want restarting in sequence with delay. We want to have complete deployment one at a time. So far I have this:
namespace :deploy do
task :sequence do
on roles(:app), in: :sequence do |host|
invoke 'deploy'
end
end
end
The problem is with invoke 'deploy'
It calls deploy for all the app servers which in turns deploy in parallel.
Finally How Do I invoke deploy task for a specific host?
Following should help you to run the deploy task in sequential mode:
task :my_task, roles: :web do
find_servers_for_task(current_task).each do |server|
run "YOUR_COMMAND", hosts: server.host
end
end
If I had that requirement, I'd probably script it. You can run Capistrano with the --hosts parameter to define which of the servers you described in your stage file (config/deploy/dev|stage|prod|somethingelse.rb) you actually want to run the command against. This can take two forms. Let's say I have three servers, test1, test2, and prod1. I can run it with a list, like cap prod --hosts=test1,test2 deploy and only test1 and test2 will receive the deployment. You can also use a regular expression to achieve the same thing, like cap prod --hosts=^test deploy.
This is documented here: http://capistranorb.com/documentation/advanced-features/host-filtering/
With this in mind, I'd probably write a script (or Makefile) which runs capistrano N time, for a different server each time.

Setting up a rake task with Resque Scheduler - Rails 4

I am on Rails 4 using the Resque Scheduler gem.
I am also using the sitemap generator gem in order to dynamically generate my sitemap.
I am having trouble figuring out the best way to schedule a rake task with resque scheduler. The sitemap generator recommends whenever, but I am assuming resque scheduler can accomplish the same thing (don't want to install another gem if I don't have to).
Does anyone know how to set this up?
I would like to run rake sitemap:refresh:no_ping every 5 hours.
I was thinking I would just schedule a background job and run it from there:
# resque_schedule.yml
update_sitemap:
every: 5h
class: "SitemapUpdater"
description: "This job refreshes the sitemap"
# sitemap_updater.rb
class SitemapUpdater
#queue = :sitemap_queue
def self.perform
# run rake task here
end
end
... however, I'm not sure if this is a good practice. Any advice would be much appreciated.
I don't see a problem with your approach, you just must be aware that the scheduler is reset during every deployment, so if you do frequent deploys, your scheduled jobs might be run later or even not run at all, as documented:
IMPORTANT: Rufus every syntax will calculate jobs scheduling time starting from the moment of deploy, resulting in resetting schedule time on every deploy, so it's probably a good idea to use it only for frequent jobs (like every 10-30 minutes), otherwise - when you use something like every 20h and deploy once-twice per day - it will schedule the job for 20 hours from deploy, resulting in a job to never be run.
You might also run the rake from system cron itself, which is an even more lightweight solution as it requires no scheduler gems at all, just the rake task, and will be scheduled reliably in time.
See e.g. this answer for setting up the "every 5 hours" frequency in crontab and you might also need to study RVM wrappers if you use RVM for your ruby project (you must call rake using the RVM wrappers in such case, e.g. call /home/deploy/.rvm/wrappers/ruby-2.3.0#mygemset/rake instead of just rake).

Set default stage with Capistrano 3

Is there a way to set a default stage in Capistrano 3?
I've tried putting set :stage, :production inside deploy.rb but that didn't work, it gives the error:
Stage not set, please call something such as `cap production deploy`,
where production is a stage you have defined
I only have one stage right now so I want to be able to just run cap deploy and have it execute on the default.
Capistrano v3 is somewhat of a wrapper around Rake, so you need to realize that what's really happening is that a production task is getting run first, followed by a deploy task.
If you debug it a little, you'll find that deploy.rb doesn't get loaded when you don't type in a stage. This is because the stage's task is where deploy.rb gets loaded: Looking at lib/setup.rb, a task is defined for each stage. When run, the stage's task sets :stage, loads up the capistrano defaults, and then finally loads your deploy.rb file.
So, an easy trick would be to tell Capistrano to invoke the stage task every time you run cap by adding this to the end of your Capfile (not your deploy.rb):
Rake::Task[:production].invoke
or, using the invoke method from Capistrano's DSL:
invoke :production
This may have some unintended consequences if you actually do use multiple stages, but if you only ever use the production stage, it should work fine.
Another easy solution could be a simple shell alias, such as alias cap='cap production', but it might not work great if you have multiple projects with different stage names.
After I cd into the RAILS Root directory, issuing the command:
cap development deploy
seems to work. Earlier I was in the app/models folder and issuing the command came back with this error:
Stage not set, please call something such as cap production deploy, where production is a stage you have defined.
The old solution works for me in Capistrano 3:
cap --version
#=> Capistrano Version: 3.3.5 (Rake Version: 10.4.2)
At the very top of the Capfile after these lines
# Load DSL and Setup Up Stages
require 'capistrano/setup'
add:
set :stage, :production
and then run you task as usual without the stage specified:
cap foo:bar
New answer for capistrano 3.6+:
It's better to use invoke :production unless Rake.application.options.show_tasks to avoid the warning which you would otherwise get with cap -T
You can add the following line to your deploy.rb, which will prevent Capistrano from expecting a stage:
set :stages, ["production"]

Run simultaneous or asynchronous tasks with Capistrano

I have a few long-running restarts of processes in my deploy.rb like:
rake assets:precompile
script/delayed_job restart
rake sunspot:solr:stop, rake sunspot:solr:start
All of these processes have to occur, but not necessarily one after another.
I was wondering if I can run the assets:precompile and the delayed_job restart simultaneously, as they don't need to happen one after another, and I could speed up my deploy time by doing them asynchronously.
I've run some Google searches but I can't find anything about it.
This is not a feature that capistrano supports.
I have been looking around for a solution and found something on the Capistrano google groups. The suggestion was to use Capistrano to run a ruby script that runs the jobs in parallel using Ruby's own threading support.
If you read the post one of the authors does ask why do these tasks need to run in parallel because you can introduce race conditions and other non-deterministic behaviour which can make the deployment process more brittle.

Resources