summaryrefslogtreecommitdiff
path: root/spec/lib/gitlab/sidekiq_middleware_spec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/lib/gitlab/sidekiq_middleware_spec.rb')
-rw-r--r--spec/lib/gitlab/sidekiq_middleware_spec.rb303
1 files changed, 150 insertions, 153 deletions
diff --git a/spec/lib/gitlab/sidekiq_middleware_spec.rb b/spec/lib/gitlab/sidekiq_middleware_spec.rb
index 0efdef0c999..5e4e79e818e 100644
--- a/spec/lib/gitlab/sidekiq_middleware_spec.rb
+++ b/spec/lib/gitlab/sidekiq_middleware_spec.rb
@@ -4,215 +4,212 @@ require 'spec_helper'
require 'sidekiq/testing'
RSpec.describe Gitlab::SidekiqMiddleware do
- before do
- stub_const('TestWorker', Class.new)
+ let(:job_args) { [0.01] }
+ let(:disabled_sidekiq_middlewares) { [] }
+ let(:chain) { Sidekiq::Middleware::Chain.new }
+ let(:queue) { 'test' }
+ let(:enabled_sidekiq_middlewares) { all_sidekiq_middlewares - disabled_sidekiq_middlewares }
+ let(:worker_class) do
+ Class.new do
+ def self.name
+ 'TestWorker'
+ end
- TestWorker.class_eval do
- include Sidekiq::Worker
include ApplicationWorker
- def perform(_arg)
+ def perform(*args)
Gitlab::SafeRequestStore['gitaly_call_actual'] = 1
Gitlab::SafeRequestStore[:gitaly_query_time] = 5
end
end
end
- around do |example|
- Sidekiq::Testing.inline! { example.run }
+ before do
+ stub_const('TestWorker', worker_class)
end
- let(:worker_class) { TestWorker }
- let(:job_args) { [0.01] }
-
- # The test sets up a new server middleware stack, ensuring that the
- # appropriate middlewares, as passed into server_configurator,
- # are invoked.
- # Additionally the test ensure that each middleware is
- # 1) not failing
- # 2) yielding exactly once
- describe '.server_configurator' do
- around do |example|
- with_sidekiq_server_middleware do |chain|
- described_class.server_configurator(
- metrics: metrics,
- arguments_logger: arguments_logger,
- memory_killer: memory_killer
- ).call(chain)
+ shared_examples "a middleware chain" do |load_balancing_enabled|
+ before do
+ allow(::Gitlab::Database::LoadBalancing).to receive(:enable?).and_return(load_balancing_enabled)
+ configurator.call(chain)
+ end
- example.run
+ it "passes through the right middlewares", :aggregate_failures do
+ enabled_sidekiq_middlewares.each do |middleware|
+ expect_next_instances_of(middleware, 1, true) do |middleware_instance|
+ expect(middleware_instance).to receive(:call).with(*middleware_expected_args).once.and_call_original
+ end
end
+
+ expect { |b| chain.invoke(*worker_args, &b) }.to yield_control.once
end
+ end
+
+ shared_examples "a middleware chain for mailer" do |load_balancing_enabled|
+ let(:worker_class) { ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper }
- let(:middleware_expected_args) { [a_kind_of(worker_class), hash_including({ 'args' => job_args }), anything] }
+ it_behaves_like "a middleware chain", load_balancing_enabled
+ end
+
+ describe '.server_configurator' do
+ let(:configurator) { described_class.server_configurator }
+ let(:worker_args) { [worker_class.new, { 'args' => job_args }, queue] }
+ let(:middleware_expected_args) { [a_kind_of(worker_class), hash_including({ 'args' => job_args }), queue] }
let(:all_sidekiq_middlewares) do
[
- Gitlab::SidekiqMiddleware::Monitor,
- Gitlab::SidekiqMiddleware::BatchLoader,
- Labkit::Middleware::Sidekiq::Server,
- Gitlab::SidekiqMiddleware::InstrumentationLogger,
- Gitlab::SidekiqVersioning::Middleware,
- Gitlab::SidekiqStatus::ServerMiddleware,
- Gitlab::SidekiqMiddleware::ServerMetrics,
- Gitlab::SidekiqMiddleware::ArgumentsLogger,
- Gitlab::SidekiqMiddleware::MemoryKiller,
- Gitlab::SidekiqMiddleware::RequestStoreMiddleware,
- Gitlab::SidekiqMiddleware::ExtraDoneLogMetadata,
- Gitlab::SidekiqMiddleware::WorkerContext::Server,
- Gitlab::SidekiqMiddleware::AdminMode::Server,
- Gitlab::SidekiqMiddleware::DuplicateJobs::Server
+ ::Gitlab::SidekiqMiddleware::Monitor,
+ ::Gitlab::SidekiqMiddleware::ServerMetrics,
+ ::Gitlab::SidekiqMiddleware::ArgumentsLogger,
+ ::Gitlab::SidekiqMiddleware::MemoryKiller,
+ ::Gitlab::SidekiqMiddleware::RequestStoreMiddleware,
+ ::Gitlab::SidekiqMiddleware::ExtraDoneLogMetadata,
+ ::Gitlab::SidekiqMiddleware::BatchLoader,
+ ::Labkit::Middleware::Sidekiq::Server,
+ ::Gitlab::SidekiqMiddleware::InstrumentationLogger,
+ ::Gitlab::Database::LoadBalancing::SidekiqServerMiddleware,
+ ::Gitlab::SidekiqMiddleware::AdminMode::Server,
+ ::Gitlab::SidekiqVersioning::Middleware,
+ ::Gitlab::SidekiqStatus::ServerMiddleware,
+ ::Gitlab::SidekiqMiddleware::WorkerContext::Server,
+ ::Gitlab::SidekiqMiddleware::DuplicateJobs::Server
]
end
- let(:enabled_sidekiq_middlewares) { all_sidekiq_middlewares - disabled_sidekiq_middlewares }
+ describe "server metrics" do
+ around do |example|
+ with_sidekiq_server_middleware do |chain|
+ described_class.server_configurator(
+ metrics: true,
+ arguments_logger: true,
+ memory_killer: true
+ ).call(chain)
- shared_examples "a server middleware chain" do
- it "passes through the right server middlewares" do
- enabled_sidekiq_middlewares.each do |middleware|
- expect_next_instance_of(middleware) do |middleware_instance|
- expect(middleware_instance).to receive(:call).with(*middleware_expected_args).once.and_call_original
- end
+ Sidekiq::Testing.inline! { example.run }
end
+ end
+ let(:gitaly_histogram) { double(:gitaly_histogram) }
- disabled_sidekiq_middlewares.each do |middleware|
- expect(middleware).not_to receive(:new)
- end
+ before do
+ allow(Gitlab::Metrics).to receive(:histogram).and_call_original
+
+ allow(Gitlab::Metrics).to receive(:histogram)
+ .with(:sidekiq_jobs_gitaly_seconds, anything, anything, anything)
+ .and_return(gitaly_histogram)
+ end
+
+ it "records correct Gitaly duration" do
+ expect(gitaly_histogram).to receive(:observe).with(anything, 5.0)
worker_class.perform_async(*job_args)
end
end
- shared_examples "a server middleware chain for mailer" do
- let(:worker_class) { ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper }
- let(:job_args) do
- [
- {
- "job_class" => "ActionMailer::MailDeliveryJob",
- "job_id" => "a180b47c-3fd6-41b8-81e9-34da61c3400e",
- "provider_job_id" => nil,
- "queue_name" => "mailers",
- "priority" => nil,
- "arguments" => [
- "Notify",
- "test_email",
- "deliver_now",
- {
- "args" => [
- "test@example.com",
- "subject",
- "body"
- ],
- ActiveJob::Arguments.const_get('RUBY2_KEYWORDS_KEY', false) => ["args"]
- }
- ],
- "executions" => 0,
- "exception_executions" => {},
- "locale" => "en",
- "timezone" => "UTC",
- "enqueued_at" => "2020-07-27T07:43:31Z"
- }
- ]
+ context "all optional middlewares on" do
+ context "when load balancing is enabled" do
+ before do
+ allow(::Gitlab::Database::LoadBalancing).to receive_message_chain(:proxy, :load_balancer, :release_host)
+ end
+
+ it_behaves_like "a middleware chain", true
+ it_behaves_like "a middleware chain for mailer", true
end
- it_behaves_like "a server middleware chain"
- end
+ context "when load balancing is disabled" do
+ let(:disabled_sidekiq_middlewares) do
+ [
+ Gitlab::Database::LoadBalancing::SidekiqServerMiddleware
+ ]
+ end
- context "all optional middlewares off" do
- let(:metrics) { false }
- let(:arguments_logger) { false }
- let(:memory_killer) { false }
- let(:disabled_sidekiq_middlewares) do
- [
- Gitlab::SidekiqMiddleware::ServerMetrics,
- Gitlab::SidekiqMiddleware::ArgumentsLogger,
- Gitlab::SidekiqMiddleware::MemoryKiller
- ]
+ it_behaves_like "a middleware chain", false
+ it_behaves_like "a middleware chain for mailer", false
end
-
- it_behaves_like "a server middleware chain"
- it_behaves_like "a server middleware chain for mailer"
end
- context "all optional middlewares on" do
- let(:metrics) { true }
- let(:arguments_logger) { true }
- let(:memory_killer) { true }
- let(:disabled_sidekiq_middlewares) { [] }
-
- it_behaves_like "a server middleware chain"
- it_behaves_like "a server middleware chain for mailer"
+ context "all optional middlewares off" do
+ let(:configurator) do
+ described_class.server_configurator(
+ metrics: false,
+ arguments_logger: false,
+ memory_killer: false
+ )
+ end
- context "server metrics" do
- let(:gitaly_histogram) { double(:gitaly_histogram) }
+ context "when load balancing is enabled" do
+ let(:disabled_sidekiq_middlewares) do
+ [
+ Gitlab::SidekiqMiddleware::ServerMetrics,
+ Gitlab::SidekiqMiddleware::ArgumentsLogger,
+ Gitlab::SidekiqMiddleware::MemoryKiller
+ ]
+ end
before do
- allow(Gitlab::Metrics).to receive(:histogram).and_call_original
-
- allow(Gitlab::Metrics).to receive(:histogram)
- .with(:sidekiq_jobs_gitaly_seconds, anything, anything, anything)
- .and_return(gitaly_histogram)
+ allow(::Gitlab::Database::LoadBalancing).to receive_message_chain(:proxy, :load_balancer, :release_host)
end
- it "records correct Gitaly duration" do
- expect(gitaly_histogram).to receive(:observe).with(anything, 5.0)
+ it_behaves_like "a middleware chain", true
+ it_behaves_like "a middleware chain for mailer", true
+ end
- worker_class.perform_async(*job_args)
+ context "when load balancing is disabled" do
+ let(:disabled_sidekiq_middlewares) do
+ [
+ Gitlab::SidekiqMiddleware::ServerMetrics,
+ Gitlab::SidekiqMiddleware::ArgumentsLogger,
+ Gitlab::SidekiqMiddleware::MemoryKiller,
+ Gitlab::Database::LoadBalancing::SidekiqServerMiddleware
+ ]
end
+
+ it_behaves_like "a middleware chain", false
+ it_behaves_like "a middleware chain for mailer", false
end
end
end
- # The test sets up a new client middleware stack. The test ensures
- # that each middleware is:
- # 1) not failing
- # 2) yielding exactly once
describe '.client_configurator' do
- let(:chain) { Sidekiq::Middleware::Chain.new }
- let(:job) { { 'args' => job_args } }
- let(:queue) { 'default' }
+ let(:configurator) { described_class.client_configurator }
let(:redis_pool) { Sidekiq.redis_pool }
- let(:middleware_expected_args) { [worker_class_arg, job, queue, redis_pool] }
- let(:expected_middlewares) do
+ let(:middleware_expected_args) { [worker_class, hash_including({ 'args' => job_args }), queue, redis_pool] }
+ let(:worker_args) { [worker_class, { 'args' => job_args }, queue, redis_pool] }
+ let(:all_sidekiq_middlewares) do
[
- ::Gitlab::SidekiqMiddleware::WorkerContext::Client,
- ::Labkit::Middleware::Sidekiq::Client,
- ::Gitlab::SidekiqMiddleware::DuplicateJobs::Client,
- ::Gitlab::SidekiqStatus::ClientMiddleware,
- ::Gitlab::SidekiqMiddleware::AdminMode::Client,
- ::Gitlab::SidekiqMiddleware::SizeLimiter::Client,
- ::Gitlab::SidekiqMiddleware::ClientMetrics
+ ::Gitlab::SidekiqMiddleware::WorkerContext::Client,
+ ::Labkit::Middleware::Sidekiq::Client,
+ ::Gitlab::SidekiqMiddleware::DuplicateJobs::Client,
+ ::Gitlab::SidekiqStatus::ClientMiddleware,
+ ::Gitlab::SidekiqMiddleware::AdminMode::Client,
+ ::Gitlab::SidekiqMiddleware::SizeLimiter::Client,
+ ::Gitlab::SidekiqMiddleware::ClientMetrics,
+ ::Gitlab::Database::LoadBalancing::SidekiqClientMiddleware
]
end
- before do
- described_class.client_configurator.call(chain)
- end
-
- shared_examples "a client middleware chain" do
- # Its possible that a middleware could accidentally omit a yield call
- # this will prevent the full middleware chain from being executed.
- # This test ensures that this does not happen
- it "invokes the chain" do
- expected_middlewares do |middleware|
- expect_any_instance_of(middleware).to receive(:call).with(*middleware_expected_args).once.ordered.and_call_original
- end
-
- expect { |b| chain.invoke(worker_class_arg, job, queue, redis_pool, &b) }.to yield_control.once
+ context "when load balancing is disabled" do
+ let(:disabled_sidekiq_middlewares) do
+ [
+ Gitlab::Database::LoadBalancing::SidekiqClientMiddleware
+ ]
end
- end
- # Sidekiq documentation states that the worker class could be a string
- # or a class reference. We should test for both
- context "handles string worker_class values" do
- let(:worker_class_arg) { worker_class.to_s }
+ it_behaves_like "a middleware chain", false
+ it_behaves_like "a middleware chain for mailer", false
- it_behaves_like "a client middleware chain"
- end
+ # Sidekiq documentation states that the worker class could be a string
+ # or a class reference. We should test for both
+ context "worker_class as string value" do
+ let(:worker_args) { [worker_class.to_s, { 'args' => job_args }, queue, redis_pool] }
+ let(:middleware_expected_args) { [worker_class.to_s, hash_including({ 'args' => job_args }), queue, redis_pool] }
- context "handles string worker_class values" do
- let(:worker_class_arg) { worker_class }
+ it_behaves_like "a middleware chain", false
+ it_behaves_like "a middleware chain for mailer", false
+ end
+ end
- it_behaves_like "a client middleware chain"
+ context "when load balancing is enabled" do
+ it_behaves_like "a middleware chain", true
+ it_behaves_like "a middleware chain for mailer", true
end
end
end