2020-03-11 20:09:34 -04:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
require 'rspec-parameterized'
|
|
|
|
|
2021-11-08 13:09:52 -05:00
|
|
|
require_relative '../../sidekiq_cluster/sidekiq_cluster'
|
|
|
|
|
|
|
|
RSpec.describe Gitlab::SidekiqCluster do # rubocop:disable RSpec/FilePath
|
2020-03-11 20:09:34 -04:00
|
|
|
describe '.start' do
|
|
|
|
it 'starts Sidekiq with the given queues, environment and options' do
|
2021-11-18 07:13:46 -05:00
|
|
|
process_options = {
|
|
|
|
pgroup: true,
|
|
|
|
err: $stderr,
|
|
|
|
out: $stdout
|
2020-03-11 20:09:34 -04:00
|
|
|
}
|
|
|
|
|
2021-12-08 10:13:43 -05:00
|
|
|
expect(Bundler).to receive(:with_original_env).and_call_original.twice
|
|
|
|
|
2021-11-18 07:13:46 -05:00
|
|
|
expect(Process).to receive(:spawn).ordered.with({
|
|
|
|
"ENABLE_SIDEKIQ_CLUSTER" => "1",
|
|
|
|
"SIDEKIQ_WORKER_ID" => "0"
|
|
|
|
},
|
|
|
|
"bundle", "exec", "sidekiq", "-c10", "-eproduction", "-t25", "-gqueues:foo", "-rfoo/bar", "-qfoo,1", process_options
|
|
|
|
)
|
|
|
|
expect(Process).to receive(:spawn).ordered.with({
|
|
|
|
"ENABLE_SIDEKIQ_CLUSTER" => "1",
|
|
|
|
"SIDEKIQ_WORKER_ID" => "1"
|
|
|
|
},
|
|
|
|
"bundle", "exec", "sidekiq", "-c10", "-eproduction", "-t25", "-gqueues:bar,baz", "-rfoo/bar", "-qbar,1", "-qbaz,1", process_options
|
|
|
|
)
|
|
|
|
|
|
|
|
described_class.start([%w(foo), %w(bar baz)], env: :production, directory: 'foo/bar', max_concurrency: 20, min_concurrency: 10)
|
2020-03-11 20:09:34 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'starts Sidekiq with the given queues and sensible default options' do
|
|
|
|
expected_options = {
|
|
|
|
env: :development,
|
|
|
|
directory: an_instance_of(String),
|
|
|
|
max_concurrency: 50,
|
|
|
|
min_concurrency: 0,
|
|
|
|
worker_id: an_instance_of(Integer),
|
2020-03-25 05:08:11 -04:00
|
|
|
timeout: 25,
|
2020-03-11 20:09:34 -04:00
|
|
|
dryrun: false
|
|
|
|
}
|
|
|
|
|
|
|
|
expect(described_class).to receive(:start_sidekiq).ordered.with(%w(foo bar baz), expected_options)
|
|
|
|
expect(described_class).to receive(:start_sidekiq).ordered.with(%w(solo), expected_options)
|
|
|
|
|
|
|
|
described_class.start([%w(foo bar baz), %w(solo)])
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe '.start_sidekiq' do
|
|
|
|
let(:first_worker_id) { 0 }
|
|
|
|
let(:options) do
|
2020-03-25 05:08:11 -04:00
|
|
|
{ env: :production, directory: 'foo/bar', max_concurrency: 20, min_concurrency: 0, worker_id: first_worker_id, timeout: 10, dryrun: false }
|
2020-03-11 20:09:34 -04:00
|
|
|
end
|
2020-08-10 23:11:00 -04:00
|
|
|
|
2020-03-11 20:09:34 -04:00
|
|
|
let(:env) { { "ENABLE_SIDEKIQ_CLUSTER" => "1", "SIDEKIQ_WORKER_ID" => first_worker_id.to_s } }
|
2020-03-25 05:08:11 -04:00
|
|
|
let(:args) { ['bundle', 'exec', 'sidekiq', anything, '-eproduction', '-t10', *([anything] * 5)] }
|
2020-03-11 20:09:34 -04:00
|
|
|
|
|
|
|
it 'starts a Sidekiq process' do
|
|
|
|
allow(Process).to receive(:spawn).and_return(1)
|
|
|
|
|
2021-11-18 01:10:36 -05:00
|
|
|
expect(Gitlab::ProcessManagement).to receive(:wait_async).with(1)
|
2020-10-08 14:08:32 -04:00
|
|
|
expect(described_class.start_sidekiq(%w(foo), **options)).to eq(1)
|
2020-03-11 20:09:34 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'handles duplicate queue names' do
|
|
|
|
allow(Process)
|
|
|
|
.to receive(:spawn)
|
|
|
|
.with(env, *args, anything)
|
|
|
|
.and_return(1)
|
|
|
|
|
2021-11-18 01:10:36 -05:00
|
|
|
expect(Gitlab::ProcessManagement).to receive(:wait_async).with(1)
|
2020-10-08 14:08:32 -04:00
|
|
|
expect(described_class.start_sidekiq(%w(foo foo bar baz), **options)).to eq(1)
|
2020-03-11 20:09:34 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'runs the sidekiq process in a new process group' do
|
|
|
|
expect(Process)
|
|
|
|
.to receive(:spawn)
|
|
|
|
.with(anything, *args, a_hash_including(pgroup: true))
|
|
|
|
.and_return(1)
|
|
|
|
|
2021-11-18 01:10:36 -05:00
|
|
|
allow(Gitlab::ProcessManagement).to receive(:wait_async)
|
2020-10-08 14:08:32 -04:00
|
|
|
expect(described_class.start_sidekiq(%w(foo bar baz), **options)).to eq(1)
|
2020-03-11 20:09:34 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-12-16 01:10:11 -05:00
|
|
|
describe '.count_by_queue' do
|
|
|
|
it 'tallies the queue counts' do
|
|
|
|
queues = [%w(foo), %w(bar baz), %w(foo)]
|
|
|
|
|
|
|
|
expect(described_class.count_by_queue(queues)).to eq(%w(foo) => 2, %w(bar baz) => 1)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-03-11 20:09:34 -04:00
|
|
|
describe '.concurrency' do
|
|
|
|
using RSpec::Parameterized::TableSyntax
|
|
|
|
|
|
|
|
where(:queue_count, :min, :max, :expected) do
|
|
|
|
2 | 0 | 0 | 3 # No min or max specified
|
|
|
|
2 | 0 | 9 | 3 # No min specified, value < max
|
|
|
|
2 | 1 | 4 | 3 # Value between min and max
|
|
|
|
2 | 4 | 5 | 4 # Value below range
|
|
|
|
5 | 2 | 3 | 3 # Value above range
|
|
|
|
2 | 1 | 1 | 1 # Value above explicit setting (min == max)
|
|
|
|
0 | 3 | 3 | 3 # Value below explicit setting (min == max)
|
|
|
|
1 | 4 | 3 | 3 # Min greater than max
|
|
|
|
end
|
|
|
|
|
|
|
|
with_them do
|
|
|
|
let(:queues) { Array.new(queue_count) }
|
|
|
|
|
|
|
|
it { expect(described_class.concurrency(queues, min, max)).to eq(expected) }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|