The problem

We have Sidekiq installed on the production server, and we use Monit to monitor its processes. The problem is that when we deploy with Capistrano, Capistrano stops the existing process and starts a new one at the end of the deploy. Meanwhile Monit, notices that the Sidekiq process has stopped, and restarts it. After the deployment, there are two Sidekiq processes running, instead of one.

The Monit recipe looks like this:

ruby
check process <%%= fetch(:sidekiq_service_name) %>
  with pidfile <%%= fetch(:sidekiq_pid) %>
  if does not exist then alert
  start program = "/bin/bash -c '<%%= fetch(:sidekiq_comand) %> -d -i 0  -P <%%= fetch(:sidekiq_pid) %> -e production -C <%%= fetch(:sidekiq_config) %> -L <%%= fetch(:sidekiq_log) %>'" with timeout 30 seconds
  stop program = "/bin/bash kill -s TERM `cat <%%= fetch(:sidekiq_pid) %>`" with timeout 30 seconds
  if totalmem is greater than 500 MB for 2 cycles then alert
    group sidekiq

The solution

The solution is to tell Monit to unmonitor the Sidekiq before deploy and monitor it again when the deployment is complete. The hooks that perform that below are taken from the capistrano-sidekiq gem, so feel free to use that gem if easier. Otherwise, read on.

Let's write the Capistrano tasks that will unmonitor/monitor Sidekiq on a recipe accessible by production stage, e.g. config/deploy/production.rb file.

ruby
namespace :sidekiq do
  namespace :monit do
    desc "Monitor sidekiq"
    task :monitor do
      on roles(:app) do
        execute "sudo /usr/bin/monit monitor #{fetch(:sidekiq_service_name)}"
      end
    end

    desc "Unmonitor sidekiq"
    task :unmonitor do
      on roles(:app) do
        execute "sudo /usr/bin/monit unmonitor #{fetch(:sidekiq_service_name)}"
      end
    end
  end
end

And then we'll tell Capistrano to run them before and after deployment:

ruby
namespace :deploy do
  after 'deploy:check',      'sidekiq:monit:unmonitor'
  after 'deploy:publishing', 'sidekiq:monit:monitor'
end

When we deploy again, all should work OK, and we'll have only one Sidekiq process running.