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

Commit

Permalink
feat(worker): "resque" support added
Browse files Browse the repository at this point in the history
Resolves #41
  • Loading branch information
ajgon committed Sep 14, 2016
1 parent b9e7b63 commit ccc13e4
Show file tree
Hide file tree
Showing 14 changed files with 253 additions and 9 deletions.
17 changes: 15 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ then [add recipes to the corresponding OpsWorks actions](#recipes).
* Worker
* Null (no worker)
* sidekiq
* resque

## Requirements

Expand Down Expand Up @@ -321,12 +322,12 @@ apply here.)

### worker

Configuration for ruby workers. Currenty `Null` (no worker) and `Sidekiq`
Configuration for ruby workers. Currenty `Resque` and `Sidekiq`
are supported. Every worker is covered by `monitd` daemon out-of-the-box.

* `app['worker']['adapter']`
* **Default:** `null`
* **Supported values:** `null`, `sidekiq`
* **Supported values:** `null`, `resque`, `sidekiq`
* Worker used to perform background tasks. `null` means no worker enabled.
* `app['worker']['process_count']`
* ** Default:** `2`
Expand All @@ -335,11 +336,23 @@ are supported. Every worker is covered by `monitd` daemon out-of-the-box.
* **Default:** `true`
* **Supported values:** `true`, `false`
* Log worker output to syslog?

#### 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](https://github.com/mperham/sidekiq/wiki/Advanced-Options#the-sidekiq-configuration-file).

#### resque

* `app['worker']['workers']`
* **Default:** `2`
* Number of resque workers
* `app['worker']['queues']`
* **Default:** `*`
* Array of queues which should be processed by resque

## Recipes

This cookbook provides five main recipes, which should be attached
Expand Down
5 changes: 5 additions & 0 deletions attributes/default.rb
Original file line number Diff line number Diff line change
Expand Up @@ -122,3 +122,8 @@
## sidekiq

default['defaults']['worker']['config'] = { 'concurrency' => 5, 'verbose' => false, 'queues' => ['default'] }

## resque

default['defaults']['worker']['queues'] = '*'
default['defaults']['worker']['workers'] = 2
5 changes: 5 additions & 0 deletions libraries/drivers_worker_base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ module Drivers
module Worker
class Base < Drivers::Base
include Drivers::Dsl::Output
include Drivers::Dsl::Packages

def setup(context)
handle_packages(context)
end

def out
handle_output(raw_out)
Expand Down
49 changes: 49 additions & 0 deletions libraries/drivers_worker_resque.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# frozen_string_literal: true
module Drivers
module Worker
class Resque < Drivers::Worker::Base
adapter :resque
allowed_engines :resque
output filter: [:process_count, :syslog, :workers, :queues]
packages debian: 'redis-server', rhel: 'redis'

def configure(context)
add_resque_monit(context)
end

def after_deploy(context)
(1..process_count).each do |process_number|
context.execute "monit restart resque_#{app['shortname']}-#{process_number}" do
retries 3
end
end
context.execute 'monit reload'
end
alias after_undeploy after_deploy

private

def add_resque_monit(context)
app_shortname = app['shortname']
deploy_to = deploy_dir(app)
output = out
env = environment

context.template File.join(node['monit']['basedir'], "resque_#{app_shortname}.monitrc") do
mode '0640'
source 'resque.monitrc.erb'
variables application: app_shortname, out: output, deploy_to: deploy_to, environment: env
end
end

def process_count
[out[:process_count].to_i, 1].max
end

def environment
framework = Drivers::Framework::Factory.build(app, node)
app['environment'].merge(framework.out[:deploy_environment] || {})
end
end
end
end
1 change: 1 addition & 0 deletions libraries/drivers_worker_sidekiq.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ class Sidekiq < Drivers::Worker::Base
adapter :sidekiq
allowed_engines :sidekiq
output filter: [:config, :process_count, :require, :syslog]
packages debian: 'redis-server', rhel: 'redis'

def configure(context)
add_sidekiq_config(context)
Expand Down
3 changes: 3 additions & 0 deletions recipes/setup.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
to '/usr/local/bin/bundler'
end
end

execute 'yum-config-manager --enable epel' if node['platform_family'] == 'rhel'

every_enabled_application do |application, _deploy|
databases = []
every_enabled_rds do |rds|
Expand Down
3 changes: 2 additions & 1 deletion spec/fixtures/node.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ def node(override = {})
},
worker: {
adapter: 'sidekiq',
require: 'lorem_ipsum.rb'
require: 'lorem_ipsum.rb',
queues: 'test_queue'
},
create_dirs_before_symlink: %(../shared/test),
purge_before_symlink: %w(public/test),
Expand Down
20 changes: 20 additions & 0 deletions spec/unit/libraries/drivers_worker_resque_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# frozen_string_literal: true
require 'spec_helper'

describe Drivers::Worker::Resque do
it 'receives and exposes app and node' do
driver = described_class.new(aws_opsworks_app, node)

expect(driver.app).to eq aws_opsworks_app
expect(driver.node).to eq node
expect(driver.options).to eq({})
end

it 'returns proper out data' do
expect(described_class.new(aws_opsworks_app, node).out).to eq(
process_count: 2,
syslog: true,
queues: 'test_queue'
)
end
end
108 changes: 107 additions & 1 deletion spec/unit/recipes/configure_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@

context 'rhel' do
it 'creates sidekiq.monitrc conf' do
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')
Expand Down Expand Up @@ -248,6 +249,7 @@

context 'debian' do
it 'creates sidekiq.monitrc conf' do
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')
Expand Down Expand Up @@ -301,13 +303,14 @@
end
end

context 'Mysql + Puma + Apache2' do
context 'Mysql + Puma + Apache2 + resque' do
let(:chef_run) do
ChefSpec::SoloRunner.new(platform: 'ubuntu', version: '14.04') do |solo_node|
deploy = node['deploy']
deploy['dummy_project']['appserver']['adapter'] = 'puma'
deploy['dummy_project']['webserver']['adapter'] = 'apache2'
deploy['dummy_project']['webserver']['keepalive_timeout'] = '65'
deploy['dummy_project']['worker']['adapter'] = 'resque'
solo_node.set['deploy'] = deploy
end.converge(described_recipe)
end
Expand Down Expand Up @@ -444,15 +447,118 @@
expect(chef_run).to run_execute('find /etc/apache2/sites-enabled -maxdepth 1 -mindepth 1 -exec rm -rf {} \;')
end

it 'creates resque.monitrc conf' do
expect(chef_run).to create_template("/etc/monit/conf.d/resque_#{aws_opsworks_app['shortname']}.monitrc")
expect(chef_run)
.to render_file("/etc/monit/conf.d/resque_#{aws_opsworks_app['shortname']}.monitrc")
.with_content('check process resque_dummy_project-1')
expect(chef_run)
.to render_file("/etc/monit/conf.d/resque_#{aws_opsworks_app['shortname']}.monitrc")
.with_content('with pidfile /srv/www/dummy_project/shared/pids/resque_dummy_project-1.pid')
expect(chef_run)
.to render_file("/etc/monit/conf.d/resque_#{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" QUEUE=test_queue VERBOSE=1 ' \
'PIDFILE=/srv/www/dummy_project/shared/pids/resque_dummy_project-1.pid COUNT=2 ' \
'bundle exec rake environment resque:work 2>&1 | logger -t resque-dummy_project-1\'" with timeout 90 seconds'
)
expect(chef_run)
.to render_file("/etc/monit/conf.d/resque_#{aws_opsworks_app['shortname']}.monitrc")
.with_content(
'stop program = "/bin/su - deploy -c ' \
'\'kill -s TERM `cat /srv/www/dummy_project/shared/pids/resque_dummy_project-1.pid`\'' \
'" with timeout 90 seconds'
)
expect(chef_run)
.to render_file("/etc/monit/conf.d/resque_#{aws_opsworks_app['shortname']}.monitrc")
.with_content('check process resque_dummy_project-2')
expect(chef_run)
.to render_file("/etc/monit/conf.d/resque_#{aws_opsworks_app['shortname']}.monitrc")
.with_content('with pidfile /srv/www/dummy_project/shared/pids/resque_dummy_project-2.pid')
expect(chef_run)
.to render_file("/etc/monit/conf.d/resque_#{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" QUEUE=test_queue VERBOSE=1 ' \
'PIDFILE=/srv/www/dummy_project/shared/pids/resque_dummy_project-2.pid COUNT=2 ' \
'bundle exec rake environment resque:work 2>&1 | logger -t resque-dummy_project-2\'" with timeout 90 seconds'
)
expect(chef_run)
.to render_file("/etc/monit/conf.d/resque_#{aws_opsworks_app['shortname']}.monitrc")
.with_content(
'stop program = "/bin/su - deploy -c ' \
'\'kill -s TERM `cat /srv/www/dummy_project/shared/pids/resque_dummy_project-2.pid`\'' \
'" with timeout 90 seconds'
)
expect(chef_run)
.to render_file("/etc/monit/conf.d/resque_#{aws_opsworks_app['shortname']}.monitrc")
.with_content('group resque_dummy_project_group')
end

context 'rhel' do
let(:chef_run_rhel) do
ChefSpec::SoloRunner.new(platform: 'amazon', version: '2015.03') do |solo_node|
deploy = node['deploy']
deploy['dummy_project']['appserver']['adapter'] = 'puma'
deploy['dummy_project']['webserver']['adapter'] = 'apache2'
deploy['dummy_project']['webserver']['keepalive_timeout'] = '65'
deploy['dummy_project']['worker']['adapter'] = 'resque'
solo_node.set['deploy'] = deploy
end.converge(described_recipe)
end

it 'creates resque.monitrc conf' do
expect(chef_run_rhel).to create_template("/etc/monit.d/resque_#{aws_opsworks_app['shortname']}.monitrc")
expect(chef_run_rhel)
.to render_file("/etc/monit.d/resque_#{aws_opsworks_app['shortname']}.monitrc")
.with_content('check process resque_dummy_project-1')
expect(chef_run_rhel)
.to render_file("/etc/monit.d/resque_#{aws_opsworks_app['shortname']}.monitrc")
.with_content('with pidfile /srv/www/dummy_project/shared/pids/resque_dummy_project-1.pid')
expect(chef_run_rhel)
.to render_file("/etc/monit.d/resque_#{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" QUEUE=test_queue VERBOSE=1 ' \
'PIDFILE=/srv/www/dummy_project/shared/pids/resque_dummy_project-1.pid COUNT=2 ' \
'bundle exec rake environment resque:work 2>&1 | logger -t resque-dummy_project-1\'" ' \
'with timeout 90 seconds'
)
expect(chef_run_rhel)
.to render_file("/etc/monit.d/resque_#{aws_opsworks_app['shortname']}.monitrc")
.with_content(
'stop program = "/bin/su - deploy -c ' \
'\'kill -s TERM `cat /srv/www/dummy_project/shared/pids/resque_dummy_project-1.pid`\'' \
'" with timeout 90 seconds'
)
expect(chef_run_rhel)
.to render_file("/etc/monit.d/resque_#{aws_opsworks_app['shortname']}.monitrc")
.with_content('check process resque_dummy_project-2')
expect(chef_run_rhel)
.to render_file("/etc/monit.d/resque_#{aws_opsworks_app['shortname']}.monitrc")
.with_content('with pidfile /srv/www/dummy_project/shared/pids/resque_dummy_project-2.pid')
expect(chef_run_rhel)
.to render_file("/etc/monit.d/resque_#{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" QUEUE=test_queue VERBOSE=1 ' \
'PIDFILE=/srv/www/dummy_project/shared/pids/resque_dummy_project-2.pid COUNT=2 ' \
'bundle exec rake environment resque:work 2>&1 | logger -t resque-dummy_project-2\'" ' \
'with timeout 90 seconds'
)
expect(chef_run_rhel)
.to render_file("/etc/monit.d/resque_#{aws_opsworks_app['shortname']}.monitrc")
.with_content(
'stop program = "/bin/su - deploy -c ' \
'\'kill -s TERM `cat /srv/www/dummy_project/shared/pids/resque_dummy_project-2.pid`\'' \
'" with timeout 90 seconds'
)
expect(chef_run_rhel)
.to render_file("/etc/monit.d/resque_#{aws_opsworks_app['shortname']}.monitrc")
.with_content('group resque_dummy_project_group')
end

it 'renders apache2 configuration files in proper place' do
expect(chef_run_rhel).to render_file("/etc/httpd/ssl/#{aws_opsworks_app['domains'].first}.key")
expect(chef_run_rhel).to render_file("/etc/httpd/ssl/#{aws_opsworks_app['domains'].first}.crt")
Expand Down
10 changes: 9 additions & 1 deletion spec/unit/recipes/deploy_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,13 @@
end
end

context 'Puma + Apache' do
context 'Puma + Apache + resque' do
let(:chef_run) do
ChefSpec::SoloRunner.new(platform: 'ubuntu', version: '14.04') do |solo_node|
deploy = node['deploy']
deploy['dummy_project']['appserver']['adapter'] = 'puma'
deploy['dummy_project']['webserver']['adapter'] = 'apache2'
deploy['dummy_project']['worker']['adapter'] = 'resque'
solo_node.set['deploy'] = deploy
end.converge(described_recipe)
end
Expand All @@ -84,6 +85,7 @@
deploy = node['deploy']
deploy['dummy_project']['appserver']['adapter'] = 'puma'
deploy['dummy_project']['webserver']['adapter'] = 'apache2'
deploy['dummy_project']['worker']['adapter'] = 'resque'
solo_node.set['deploy'] = deploy
end.converge(described_recipe)
end
Expand All @@ -103,6 +105,12 @@
expect(chef_run_rhel).to run_execute('stop puma')
expect(chef_run_rhel).to run_execute('start puma')
end

it 'restarts resques via monit' do
expect(chef_run).to run_execute('monit reload')
expect(chef_run).to run_execute("monit restart resque_#{aws_opsworks_app['shortname']}-1")
expect(chef_run).to run_execute("monit restart resque_#{aws_opsworks_app['shortname']}-2")
end
end

it 'empty node[\'deploy\']' do
Expand Down
Loading

0 comments on commit ccc13e4

Please sign in to comment.