Skip to content
This repository has been archived by the owner on Dec 31, 2022. It is now read-only.

Commit

Permalink
feature(sidekiq): add multiple configs
Browse files Browse the repository at this point in the history
BREAKING CHANGE:

`app['worker']['config']` for sidekiq is now an Array. However fallback
is supported, so you don't have to change your stack.json if you don't
need to.

Keep in mind, that filenames for sidekiq monit and configurations
changed:

* Configurations changed from `sidekiq_1.yml` to `sidekiq_c1_p1.yml`
* Pids changed from `sidekiq-app-1.pid` to `sidekiq-app-c1-p1.yml`
* Logs changed from `sidekiq-app-1.log` to `sidekiq-app-c1-p1.log`
  • Loading branch information
ajgon committed May 9, 2017
1 parent 282705a commit cd54b58
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 75 deletions.
6 changes: 3 additions & 3 deletions docs/source/attributes.rst
Expand Up @@ -477,9 +477,9 @@ sidekiq

- ``app['worker']['config']``

- Configuration parameters which will be directly passed to the worker.
For example, for ``sidekiq`` they will be serialized to
`sidekiq.yml config file`_.
- Configuration parameters which will be directly passed to the worker. Accepts array
of sidekiq configs - if provided, multiple workers will be configured with given parameters
for each element of an array.

delayed\_job
^^^^^^^^^^^^
Expand Down
78 changes: 53 additions & 25 deletions libraries/drivers_worker_sidekiq.rb
Expand Up @@ -31,44 +31,72 @@ def shutdown

private

# rubocop:disable Metrics/MethodLength
def add_sidekiq_config
deploy_to = deploy_dir(app)
config = configuration

(1..process_count).each do |process_number|
context.template File.join(deploy_to, File.join('shared', 'config', "sidekiq_#{process_number}.yml")) do
owner node['deployer']['user']
group www_group
source 'sidekiq.conf.yml.erb'
variables config: config

configuration.each.with_index do |config, config_number|
(1..process_count).each do |process_number|
context.template File.join(
deploy_to, File.join('shared', 'config', "sidekiq_c#{config_number + 1}_p#{process_number}.yml")
) do
owner node['deployer']['user']
group www_group
source 'sidekiq.conf.yml.erb'
variables config: config
end
end
end
end
# rubocop:enable Metrics/MethodLength

def quiet_sidekiq
(1..process_count).each do |process_number|
pid_file = pid_file(process_number)
Chef::Log.info("Quiet Sidekiq process if exists: #{pid_file}")
next unless File.file?(pid_file) && pid_exists?(File.open(pid_file).read)
context.execute "/bin/su - #{node['deployer']['user']} -c 'kill -s USR1 `cat #{pid_file}`'"
configuration.each.with_index do |_config, config_number|
(1..process_count).each do |process_number|
pid_file = pid_file(process_number, config_number)
Chef::Log.info("Quiet Sidekiq process if exists: #{pid_file}")
next unless File.file?(pid_file) && pid_exists?(File.open(pid_file).read)
context.execute "/bin/su - #{node['deployer']['user']} -c 'kill -s USR1 `cat #{pid_file}`'"
end
end
end

def stop_sidekiq
(1..process_count).each do |process_number|
pid_file = pid_file(process_number)
timeout = (out[:config]['timeout'] || 8).to_i

context.execute(
"/bin/su - #{node['deployer']['user']} -c 'cd #{File.join(deploy_dir(app), 'current')} && " \
"#{environment.map { |k, v| "#{k}=\"#{v}\"" }.join(' ')} " \
"bundle exec sidekiqctl stop #{pid_file} #{timeout}'"
)
configuration.each.with_index do |_config, config_number|
(1..process_count).each do |process_number|
pid_file = pid_file(process_number, config_number)
tout = (out[:config]['timeout'] || 8).to_i

context.execute(
"/bin/su - #{node['deployer']['user']} -c 'cd #{File.join(deploy_dir(app), 'current')} && " \
"#{environment.map { |k, v| "#{k}=\"#{v}\"" }.join(' ')} bundle exec sidekiqctl stop #{pid_file} #{tout}'"
)
end
end
end

def restart_monit
configuration.each.with_index do |_config, config_number|
(1..process_count).each do |process_number|
context.execute "monit restart #{adapter}_#{app['shortname']}-c#{config_number + 1}-p#{process_number}" do
retries 3
end
end
end
end

def unmonitor_monit
configuration.each.with_index do |_config, config_number|
(1..process_count).each do |process_number|
context.execute "monit unmonitor #{adapter}_#{app['shortname']}-c#{config_number + 1}-p#{process_number}" do
retries 3
end
end
end
end

def pid_file(process_number)
"#{deploy_dir(app)}/shared/pids/sidekiq_#{app['shortname']}-#{process_number}.pid"
def pid_file(process_number, config_number)
"#{deploy_dir(app)}/shared/pids/sidekiq_#{app['shortname']}-c#{config_number + 1}-p#{process_number}.pid"
end

def pid_exists?(pid)
Expand All @@ -79,7 +107,7 @@ def pid_exists?(pid)
end

def configuration
JSON.parse(out[:config].to_json, symbolize_names: true)
Array.wrap(JSON.parse(out[:config].to_json, symbolize_names: true))
end
end
end
Expand Down
52 changes: 26 additions & 26 deletions spec/unit/recipes/configure_spec.rb
Expand Up @@ -202,10 +202,10 @@

it 'creates sidekiq.conf.yml' do
expect(chef_run)
.to render_file("/srv/www/#{aws_opsworks_app['shortname']}/shared/config/sidekiq_1.yml")
.to render_file("/srv/www/#{aws_opsworks_app['shortname']}/shared/config/sidekiq_c1_p1.yml")
.with_content("---\n:concurrency: 5\n:verbose: false\n:queues:\n- default")
expect(chef_run)
.to render_file("/srv/www/#{aws_opsworks_app['shortname']}/shared/config/sidekiq_2.yml")
.to render_file("/srv/www/#{aws_opsworks_app['shortname']}/shared/config/sidekiq_c1_p2.yml")
.with_content("---\n:concurrency: 5\n:verbose: false\n:queues:\n- default")
end

Expand All @@ -214,51 +214,51 @@
expect(chef_run_rhel).to create_template("/etc/monit.d/sidekiq_#{aws_opsworks_app['shortname']}.monitrc")
expect(chef_run_rhel)
.to render_file("/etc/monit.d/sidekiq_#{aws_opsworks_app['shortname']}.monitrc")
.with_content('check process sidekiq_dummy_project-1')
.with_content('check process sidekiq_dummy_project-c1-p1')
expect(chef_run_rhel)
.to render_file("/etc/monit.d/sidekiq_#{aws_opsworks_app['shortname']}.monitrc")
.with_content('with pidfile /srv/www/dummy_project/shared/pids/sidekiq_dummy_project-1.pid')
.with_content('with pidfile /srv/www/dummy_project/shared/pids/sidekiq_dummy_project-c1-p1.pid')
expect(chef_run_rhel)
.to render_file("/etc/monit.d/sidekiq_#{aws_opsworks_app['shortname']}.monitrc")
.with_content(
'start program = "/bin/su - deploy -c \'cd /srv/www/dummy_project/current && ENV_VAR1="test" ' \
'ENV_VAR2="some data" RAILS_ENV="staging" bundle exec sidekiq ' \
'-C /srv/www/dummy_project/shared/config/sidekiq_1.yml ' \
'-C /srv/www/dummy_project/shared/config/sidekiq_c1_p1.yml ' \
'-i 0 ' \
'-P /srv/www/dummy_project/shared/pids/sidekiq_dummy_project-1.pid ' \
'-P /srv/www/dummy_project/shared/pids/sidekiq_dummy_project-c1-p1.pid ' \
'-r /srv/www/dummy_project/current/lorem_ipsum.rb 2>&1 ' \
'| logger -t sidekiq-dummy_project-1\'" with timeout 90 seconds'
'| logger -t sidekiq-dummy_project-c1-p1\'" with timeout 90 seconds'
)
expect(chef_run_rhel)
.to render_file("/etc/monit.d/sidekiq_#{aws_opsworks_app['shortname']}.monitrc")
.with_content(
'stop program = "/bin/su - deploy -c \'cd /srv/www/dummy_project/current && ENV_VAR1="test" ' \
'ENV_VAR2="some data" RAILS_ENV="staging" bundle exec sidekiqctl stop ' \
'/srv/www/dummy_project/shared/pids/sidekiq_dummy_project-1.pid 8\'" with timeout 18 seconds'
'/srv/www/dummy_project/shared/pids/sidekiq_dummy_project-c1-p1.pid 8\'" with timeout 18 seconds'
)
expect(chef_run_rhel)
.to render_file("/etc/monit.d/sidekiq_#{aws_opsworks_app['shortname']}.monitrc")
.with_content('check process sidekiq_dummy_project-2')
.with_content('check process sidekiq_dummy_project-c1-p2')
expect(chef_run_rhel)
.to render_file("/etc/monit.d/sidekiq_#{aws_opsworks_app['shortname']}.monitrc")
.with_content('with pidfile /srv/www/dummy_project/shared/pids/sidekiq_dummy_project-2.pid')
.with_content('with pidfile /srv/www/dummy_project/shared/pids/sidekiq_dummy_project-c1-p2.pid')
expect(chef_run_rhel)
.to render_file("/etc/monit.d/sidekiq_#{aws_opsworks_app['shortname']}.monitrc")
.with_content(
'start program = "/bin/su - deploy -c \'cd /srv/www/dummy_project/current && ENV_VAR1="test" ' \
'ENV_VAR2="some data" RAILS_ENV="staging" bundle exec sidekiq ' \
'-C /srv/www/dummy_project/shared/config/sidekiq_2.yml ' \
'-C /srv/www/dummy_project/shared/config/sidekiq_c1_p2.yml ' \
'-i 1 ' \
'-P /srv/www/dummy_project/shared/pids/sidekiq_dummy_project-2.pid ' \
'-P /srv/www/dummy_project/shared/pids/sidekiq_dummy_project-c1-p2.pid ' \
'-r /srv/www/dummy_project/current/lorem_ipsum.rb 2>&1 ' \
'| logger -t sidekiq-dummy_project-2\'" with timeout 90 seconds'
'| logger -t sidekiq-dummy_project-c1-p2\'" with timeout 90 seconds'
)
expect(chef_run_rhel)
.to render_file("/etc/monit.d/sidekiq_#{aws_opsworks_app['shortname']}.monitrc")
.with_content(
'stop program = "/bin/su - deploy -c \'cd /srv/www/dummy_project/current && ENV_VAR1="test" ' \
'ENV_VAR2="some data" RAILS_ENV="staging" bundle exec sidekiqctl stop ' \
'/srv/www/dummy_project/shared/pids/sidekiq_dummy_project-2.pid 8\'" with timeout 18 seconds'
'/srv/www/dummy_project/shared/pids/sidekiq_dummy_project-c1-p2.pid 8\'" with timeout 18 seconds'
)
expect(chef_run_rhel)
.to render_file("/etc/monit.d/sidekiq_#{aws_opsworks_app['shortname']}.monitrc")
Expand All @@ -272,51 +272,51 @@
expect(chef_run).to create_template("/etc/monit/conf.d/sidekiq_#{aws_opsworks_app['shortname']}.monitrc")
expect(chef_run)
.to render_file("/etc/monit/conf.d/sidekiq_#{aws_opsworks_app['shortname']}.monitrc")
.with_content('check process sidekiq_dummy_project-1')
.with_content('check process sidekiq_dummy_project-c1-p1')
expect(chef_run)
.to render_file("/etc/monit/conf.d/sidekiq_#{aws_opsworks_app['shortname']}.monitrc")
.with_content('with pidfile /srv/www/dummy_project/shared/pids/sidekiq_dummy_project-1.pid')
.with_content('with pidfile /srv/www/dummy_project/shared/pids/sidekiq_dummy_project-c1-p1.pid')
expect(chef_run)
.to render_file("/etc/monit/conf.d/sidekiq_#{aws_opsworks_app['shortname']}.monitrc")
.with_content(
'start program = "/bin/su - deploy -c \'cd /srv/www/dummy_project/current && ENV_VAR1="test" ' \
'ENV_VAR2="some data" RAILS_ENV="staging" bundle exec sidekiq ' \
'-C /srv/www/dummy_project/shared/config/sidekiq_1.yml ' \
'-C /srv/www/dummy_project/shared/config/sidekiq_c1_p1.yml ' \
'-i 0 ' \
'-P /srv/www/dummy_project/shared/pids/sidekiq_dummy_project-1.pid ' \
'-P /srv/www/dummy_project/shared/pids/sidekiq_dummy_project-c1-p1.pid ' \
'-r /srv/www/dummy_project/current/lorem_ipsum.rb 2>&1 ' \
'| logger -t sidekiq-dummy_project-1\'" with timeout 90 seconds'
'| logger -t sidekiq-dummy_project-c1-p1\'" with timeout 90 seconds'
)
expect(chef_run)
.to render_file("/etc/monit/conf.d/sidekiq_#{aws_opsworks_app['shortname']}.monitrc")
.with_content(
'stop program = "/bin/su - deploy -c \'cd /srv/www/dummy_project/current && ENV_VAR1="test" ' \
'ENV_VAR2="some data" RAILS_ENV="staging" bundle exec sidekiqctl stop ' \
'/srv/www/dummy_project/shared/pids/sidekiq_dummy_project-1.pid 8\'" with timeout 18 seconds'
'/srv/www/dummy_project/shared/pids/sidekiq_dummy_project-c1-p1.pid 8\'" with timeout 18 seconds'
)
expect(chef_run)
.to render_file("/etc/monit/conf.d/sidekiq_#{aws_opsworks_app['shortname']}.monitrc")
.with_content('check process sidekiq_dummy_project-2')
.with_content('check process sidekiq_dummy_project-c1-p2')
expect(chef_run)
.to render_file("/etc/monit/conf.d/sidekiq_#{aws_opsworks_app['shortname']}.monitrc")
.with_content('with pidfile /srv/www/dummy_project/shared/pids/sidekiq_dummy_project-2.pid')
.with_content('with pidfile /srv/www/dummy_project/shared/pids/sidekiq_dummy_project-c1-p2.pid')
expect(chef_run)
.to render_file("/etc/monit/conf.d/sidekiq_#{aws_opsworks_app['shortname']}.monitrc")
.with_content(
'start program = "/bin/su - deploy -c \'cd /srv/www/dummy_project/current && ENV_VAR1="test" ' \
'ENV_VAR2="some data" RAILS_ENV="staging" bundle exec sidekiq ' \
'-C /srv/www/dummy_project/shared/config/sidekiq_2.yml ' \
'-C /srv/www/dummy_project/shared/config/sidekiq_c1_p2.yml ' \
'-i 1 ' \
'-P /srv/www/dummy_project/shared/pids/sidekiq_dummy_project-2.pid ' \
'-P /srv/www/dummy_project/shared/pids/sidekiq_dummy_project-c1-p2.pid ' \
'-r /srv/www/dummy_project/current/lorem_ipsum.rb 2>&1 ' \
'| logger -t sidekiq-dummy_project-2\'" with timeout 90 seconds'
'| logger -t sidekiq-dummy_project-c1-p2\'" with timeout 90 seconds'
)
expect(chef_run)
.to render_file("/etc/monit/conf.d/sidekiq_#{aws_opsworks_app['shortname']}.monitrc")
.with_content(
'stop program = "/bin/su - deploy -c \'cd /srv/www/dummy_project/current && ENV_VAR1="test" ' \
'ENV_VAR2="some data" RAILS_ENV="staging" bundle exec sidekiqctl stop ' \
'/srv/www/dummy_project/shared/pids/sidekiq_dummy_project-2.pid 8\'" with timeout 18 seconds'
'/srv/www/dummy_project/shared/pids/sidekiq_dummy_project-c1-p2.pid 8\'" with timeout 18 seconds'
)
expect(chef_run)
.to render_file("/etc/monit/conf.d/sidekiq_#{aws_opsworks_app['shortname']}.monitrc")
Expand Down
4 changes: 2 additions & 2 deletions spec/unit/recipes/deploy_spec.rb
Expand Up @@ -105,8 +105,8 @@
end

it 'restarts sidekiqs via monit' do
expect(chef_run).to run_execute("monit restart sidekiq_#{aws_opsworks_app['shortname']}-1")
expect(chef_run).to run_execute("monit restart sidekiq_#{aws_opsworks_app['shortname']}-2")
expect(chef_run).to run_execute("monit restart sidekiq_#{aws_opsworks_app['shortname']}-c1-p1")
expect(chef_run).to run_execute("monit restart sidekiq_#{aws_opsworks_app['shortname']}-c1-p2")
end
end

Expand Down
8 changes: 4 additions & 4 deletions spec/unit/recipes/shutdown_spec.rb
Expand Up @@ -27,23 +27,23 @@

context 'safely shutdown sidekiq' do
it 'unmonitors sidekiq processes' do
expect(chef_run).to run_execute('monit unmonitor sidekiq_dummy_project-1')
expect(chef_run).to run_execute('monit unmonitor sidekiq_dummy_project-2')
expect(chef_run).to run_execute('monit unmonitor sidekiq_dummy_project-c1-p1')
expect(chef_run).to run_execute('monit unmonitor sidekiq_dummy_project-c1-p2')
end

it 'shutsdown sidekiq processes' do
expect(chef_run).to(
run_execute(
'/bin/su - deploy -c \'cd /srv/www/dummy_project/current && ENV_VAR1="test" ' \
'ENV_VAR2="some data" RAILS_ENV="staging" bundle exec sidekiqctl stop ' \
'/srv/www/dummy_project/shared/pids/sidekiq_dummy_project-1.pid 8\''
'/srv/www/dummy_project/shared/pids/sidekiq_dummy_project-c1-p1.pid 8\''
)
)
expect(chef_run).to(
run_execute(
'/bin/su - deploy -c \'cd /srv/www/dummy_project/current && ENV_VAR1="test" ' \
'ENV_VAR2="some data" RAILS_ENV="staging" bundle exec sidekiqctl stop ' \
'/srv/www/dummy_project/shared/pids/sidekiq_dummy_project-2.pid 8\''
'/srv/www/dummy_project/shared/pids/sidekiq_dummy_project-c1-p2.pid 8\''
)
)
end
Expand Down
4 changes: 2 additions & 2 deletions spec/unit/recipes/undeploy_spec.rb
Expand Up @@ -35,8 +35,8 @@
end

it 'restarts sidekiqs via monit' do
expect(chef_run).to run_execute("monit restart sidekiq_#{aws_opsworks_app['shortname']}-1")
expect(chef_run).to run_execute("monit restart sidekiq_#{aws_opsworks_app['shortname']}-2")
expect(chef_run).to run_execute("monit restart sidekiq_#{aws_opsworks_app['shortname']}-c1-p1")
expect(chef_run).to run_execute("monit restart sidekiq_#{aws_opsworks_app['shortname']}-c1-p2")
end
end

Expand Down
27 changes: 14 additions & 13 deletions templates/default/sidekiq.monitrc.erb
@@ -1,15 +1,16 @@
<% ([@out[:process_count].to_i || 1].max).times do |n| %>
<% identifier = "#{@application}-#{n+1}" %>
<% conf_file = "#{@deploy_to}/shared/config/sidekiq_#{n+1}.yml" %>
<% pid_file = "#{@deploy_to}/shared/pids/sidekiq_#{identifier}.pid" %>
<% syslog = !!@out[:syslog] ? "2>&1 | logger -t sidekiq-#{identifier}" : '' %>
<% to_require = @out[:require].present? ? " -r #{File.join(@deploy_to, 'current', @out[:require])}" : '' %>
<% timeout = (@out[:config]['timeout'] || 8).to_i %>

check process sidekiq_<%= identifier.to_s %>
with pidfile <%= pid_file.to_s %>
start program = "/bin/su - <%= node['deployer']['user'] %> -c 'cd <%= File.join(@deploy_to, 'current') %> && <%= @environment.map { |k, v| "#{k}=\"#{v}\"" }.join(' ') %> bundle exec sidekiq -C <%= conf_file.to_s %> -i <%= n %> -P <%= pid_file.to_s %><%= to_require.to_s %> <%= syslog.to_s %>'" with timeout 90 seconds
stop program = "/bin/su - <%= node['deployer']['user'] %> -c 'cd <%= File.join(@deploy_to, 'current') %> && <%= @environment.map { |k, v| "#{k}=\"#{v}\"" }.join(' ') %> bundle exec sidekiqctl stop <%= pid_file %> <%= timeout %>'" with timeout <%= timeout + 10 %> seconds
group sidekiq_<%= @application.to_s %>_group
<% Array.wrap(@out[:config]).each.with_index do |config, config_number| %>
<% ([@out[:process_count].to_i || 1].max).times do |n| %>
<% identifier = "#{@application}-c#{config_number+1}-p#{n+1}" %>
<% conf_file = "#{@deploy_to}/shared/config/sidekiq_c#{config_number+1}_p#{n+1}.yml" %>
<% pid_file = "#{@deploy_to}/shared/pids/sidekiq_#{identifier}.pid" %>
<% syslog = !!@out[:syslog] ? "2>&1 | logger -t sidekiq-#{identifier}" : '' %>
<% to_require = @out[:require].present? ? " -r #{File.join(@deploy_to, 'current', @out[:require])}" : '' %>
<% timeout = (config['timeout'] || 8).to_i %>

check process sidekiq_<%= identifier.to_s %>
with pidfile <%= pid_file.to_s %>
start program = "/bin/su - <%= node['deployer']['user'] %> -c 'cd <%= File.join(@deploy_to, 'current') %> && <%= @environment.map { |k, v| "#{k}=\"#{v}\"" }.join(' ') %> bundle exec sidekiq -C <%= conf_file.to_s %> -i <%= n %> -P <%= pid_file.to_s %><%= to_require.to_s %> <%= syslog.to_s %>'" with timeout 90 seconds
stop program = "/bin/su - <%= node['deployer']['user'] %> -c 'cd <%= File.join(@deploy_to, 'current') %> && <%= @environment.map { |k, v| "#{k}=\"#{v}\"" }.join(' ') %> bundle exec sidekiqctl stop <%= pid_file %> <%= timeout %>'" with timeout <%= timeout + 10 %> seconds
group sidekiq_<%= @application.to_s %>_group
<% end %>
<% end %>

0 comments on commit cd54b58

Please sign in to comment.