Skip to content

Commit

Permalink
[OPS-2310] Sidekiq parallel (#16)
Browse files Browse the repository at this point in the history
* [OPS-2310] Sidekiq parallel

* Update usage

* update config spec
  • Loading branch information
louman authored Mar 22, 2018
1 parent dc4852c commit 67a2fc7
Show file tree
Hide file tree
Showing 13 changed files with 141 additions and 21 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@
/coverage/
/test.db
/*.gem
.byebug_history
13 changes: 13 additions & 0 deletions docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,19 @@ Patches::Config.configure do |config|
end
```

### Running patches in parallel for tenants

If you are using the Apartment gem, you can run the patches for each tenant in parallel. Just set the config ```sidekiq_parallel``` to ```true``` and you're good to go.

```
Patches::Config.configure do |config|
config.use_sidekiq = true
config.sidekiq_parallel = true
end
```

*Note:* Make sure your sidekiq queue is able to process concurrent jobs. You can use ```config.sidekiq_options``` to customise it.

## Creating Patches

Generate a patch
Expand Down
4 changes: 3 additions & 1 deletion lib/patches.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@ def self.logger=(log)
end

require "patches/base"
require "patches/config"
require "patches/tenant_run_concern"
require "patches/tenant_worker" if defined?(Sidekiq)
require "patches/engine" if defined?(Rails)
require "patches/patch"
require "patches/pending"
require "patches/runner"
require "patches/tenant_runner"
require "patches/config"
require "patches/notifier"
require "patches/worker" if defined?(Sidekiq)
2 changes: 1 addition & 1 deletion lib/patches/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def configure
end

class Configuration
attr_accessor :use_sidekiq, :sidekiq_queue, :sidekiq_options, :use_hipchat, :hipchat_options
attr_accessor :use_sidekiq, :sidekiq_queue, :sidekiq_options, :use_hipchat, :hipchat_options, :sidekiq_parallel

def initialize
@sidekiq_queue = 'default'
Expand Down
8 changes: 8 additions & 0 deletions lib/patches/tenant_run_concern.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module Patches
module TenantRunConcern
def run(tenant_name, path = nil)
Apartment::Tenant.switch(tenant_name)
Patches::Runner.new(path).perform
end
end
end
20 changes: 12 additions & 8 deletions lib/patches/tenant_runner.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
class Patches::TenantRunner
include Patches::TenantRunConcern
attr_accessor :path

def initialize(path: nil, tenants: nil)
Expand All @@ -8,19 +9,22 @@ def initialize(path: nil, tenants: nil)

def perform
Patches.logger.info("Patches tenant runner for: #{tenants.join(',')}")

tenants.each do |tenant|
Apartment::Tenant.switch(tenant)
runner = build
runner.perform
if parallel?
Patches::TenantWorker.perform_async(tenant, path)
else
run(tenant, path)
end
end
end

def build
Patches::Runner.new(path)
end

def tenants
@tenants ||= (Apartment.tenant_names || [])
end

private

def parallel?
Patches::Config.configuration.sidekiq_parallel
end
end
12 changes: 12 additions & 0 deletions lib/patches/tenant_worker.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
require 'sidekiq'

class Patches::TenantWorker
include Sidekiq::Worker
include Patches::TenantRunConcern

sidekiq_options Patches::Config.configuration.sidekiq_options

def perform(tenant_name, path)
run(tenant_name, path)
end
end
2 changes: 1 addition & 1 deletion lib/patches/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module Patches
VERSION = "2.2.0"
VERSION = "2.3.0"
end
1 change: 1 addition & 0 deletions patches.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,5 @@ Gem::Specification.new do |spec|
spec.add_development_dependency "sidekiq", "~> 3.4.1"
spec.add_development_dependency "hipchat"
spec.add_development_dependency "webmock"
spec.add_development_dependency "byebug"
end
24 changes: 21 additions & 3 deletions spec/config_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,19 @@

describe '#use_sidekiq' do
subject { patches_config.use_sidekiq }
before { patches_config.use_sidekiq = true }

it 'is the configured value' do
expect(subject).to eq(true)
context 'when set' do
before { patches_config.use_sidekiq = true }

it 'is the configured value' do
expect(subject).to be_truthy
end
end

context 'when not configured' do
it 'returns a falsey value' do
expect(subject).to be_falsey
end
end
end

Expand Down Expand Up @@ -55,6 +64,15 @@
end
end

describe '#sidekiq_parallel' do
subject { patches_config.sidekiq_parallel }
before { patches_config.sidekiq_parallel = true }

it 'is the configured value' do
expect(subject).to eq(true)
end
end

describe '#use_hipchat' do
subject { patches_config.use_hipchat }
before { patches_config.use_hipchat = true }
Expand Down
28 changes: 28 additions & 0 deletions spec/tenant_run_concern_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
require 'spec_helper'
require "patches/tenant_run_concern"

module Apartment
module Tenant
end
end

module Patches
class DummyRun
include TenantRunConcern
end
end

describe Patches::TenantRunConcern do
subject { Patches::DummyRun.new }

let(:runner) { double(:runner) }

describe '#run' do
it 'calls instance perform' do
expect(Apartment::Tenant).to receive(:switch).with('test')
expect(Patches::Runner).to receive(:new).with('path').and_return(runner)
expect(runner).to receive(:perform)
subject.run('test', 'path')
end
end
end
36 changes: 29 additions & 7 deletions spec/tenant_runner_spec.rb
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
require 'spec_helper'
require 'sidekiq/testing'

module Apartment
module Tenant
end
end

require 'patches/tenant_runner'
require "patches/tenant_worker"

describe Patches::TenantRunner do
let(:runner) { double('Runner') }

before do
Sidekiq::Testing.fake!
allow(Patches).to receive(:default_path).and_return('')
end

Expand All @@ -21,16 +24,35 @@ module Tenant
end

context 'perform' do
before do
expect(Apartment).to receive(:tenant_names).and_return(['test'])
end
let(:tenant_names) { ['test'] }

before { expect(Apartment).to receive(:tenant_names).and_return(tenant_names) }

specify do
expect(subject.tenants).to eql(['test'])
expect(runner).to receive(:perform).and_return(true)
expect(subject).to receive(:build).and_return(runner)
expect(Apartment::Tenant).to receive(:switch).with('test')
expect(subject.perform).to eql(['test'])
expect(subject).to receive(:run).with('test', nil)
expect { subject.perform }.not_to change(Patches::TenantWorker.jobs, :size)
end

context 'parallel' do
before { Patches::Config.configuration.sidekiq_parallel = true }

specify do
expect(subject.tenants).to eql(['test'])
expect(Patches::TenantWorker).to receive(:perform_async).with('test', nil).and_call_original
expect { subject.perform }.to change(Patches::TenantWorker.jobs, :size).by(1)
end

context 'for multiple tenants' do
let(:tenant_names) { ['test', 'test2'] }

specify do
expect(subject.tenants).to eql(['test', 'test2'])
expect(Patches::TenantWorker).to receive(:perform_async).with('test', nil).and_call_original
expect(Patches::TenantWorker).to receive(:perform_async).with('test2', nil).and_call_original
expect { subject.perform }.to change(Patches::TenantWorker.jobs, :size).by(2)
end
end
end
end
end
11 changes: 11 additions & 0 deletions spec/tenant_worker_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
require 'spec_helper'
require "patches/tenant_worker"

describe Patches::TenantWorker do
describe '#perform' do
specify do
is_expected.to receive(:run).with('test', 'path')
subject.perform('test', 'path')
end
end
end

0 comments on commit 67a2fc7

Please sign in to comment.