cca61980d5
This ensures that we have more visibility in the number of SQL queries that are executed in web requests. The current threshold is hardcoded to 100 as we will rarely (maybe once or twice) change it. In production and development we use Sentry if enabled, in the test environment we raise an error. This feature is also only enabled in production/staging when running on GitLab.com as it's not very useful to other users.
144 lines
3.8 KiB
Ruby
144 lines
3.8 KiB
Ruby
require 'spec_helper'
|
|
|
|
describe Gitlab::QueryLimiting::Transaction do
|
|
after do
|
|
Thread.current[described_class::THREAD_KEY] = nil
|
|
end
|
|
|
|
describe '.current' do
|
|
it 'returns nil when there is no transaction' do
|
|
expect(described_class.current).to be_nil
|
|
end
|
|
|
|
it 'returns the transaction when present' do
|
|
Thread.current[described_class::THREAD_KEY] = described_class.new
|
|
|
|
expect(described_class.current).to be_an_instance_of(described_class)
|
|
end
|
|
end
|
|
|
|
describe '.run' do
|
|
it 'runs a transaction and returns it and its return value' do
|
|
trans, ret = described_class.run do
|
|
10
|
|
end
|
|
|
|
expect(trans).to be_an_instance_of(described_class)
|
|
expect(ret).to eq(10)
|
|
end
|
|
|
|
it 'removes the transaction from the current thread upon completion' do
|
|
described_class.run do
|
|
10
|
|
end
|
|
|
|
expect(Thread.current[described_class::THREAD_KEY]).to be_nil
|
|
end
|
|
end
|
|
|
|
describe '#act_upon_results' do
|
|
context 'when the query threshold is not exceeded' do
|
|
it 'does nothing' do
|
|
trans = described_class.new
|
|
|
|
expect(trans).not_to receive(:raise)
|
|
|
|
trans.act_upon_results
|
|
end
|
|
end
|
|
|
|
context 'when the query threshold is exceeded' do
|
|
let(:transaction) do
|
|
trans = described_class.new
|
|
trans.count = described_class::THRESHOLD + 1
|
|
|
|
trans
|
|
end
|
|
|
|
it 'raises an error when this is enabled' do
|
|
expect { transaction.act_upon_results }
|
|
.to raise_error(described_class::ThresholdExceededError)
|
|
end
|
|
|
|
it 'reports the error in Sentry if raising an error is disabled' do
|
|
expect(transaction)
|
|
.to receive(:raise_error?)
|
|
.and_return(false)
|
|
|
|
expect(Raven)
|
|
.to receive(:capture_exception)
|
|
.with(an_instance_of(described_class::ThresholdExceededError))
|
|
|
|
transaction.act_upon_results
|
|
end
|
|
end
|
|
end
|
|
|
|
describe '#increment' do
|
|
it 'increments the number of executed queries' do
|
|
transaction = described_class.new
|
|
|
|
expect(transaction.count).to be_zero
|
|
|
|
transaction.increment
|
|
|
|
expect(transaction.count).to eq(1)
|
|
end
|
|
end
|
|
|
|
describe '#raise_error?' do
|
|
it 'returns true in a test environment' do
|
|
transaction = described_class.new
|
|
|
|
expect(transaction.raise_error?).to eq(true)
|
|
end
|
|
|
|
it 'returns false in a production environment' do
|
|
transaction = described_class.new
|
|
|
|
expect(Rails.env)
|
|
.to receive(:test?)
|
|
.and_return(false)
|
|
|
|
expect(transaction.raise_error?).to eq(false)
|
|
end
|
|
end
|
|
|
|
describe '#threshold_exceeded?' do
|
|
it 'returns false when the threshold is not exceeded' do
|
|
transaction = described_class.new
|
|
|
|
expect(transaction.threshold_exceeded?).to eq(false)
|
|
end
|
|
|
|
it 'returns true when the threshold is exceeded' do
|
|
transaction = described_class.new
|
|
transaction.count = described_class::THRESHOLD + 1
|
|
|
|
expect(transaction.threshold_exceeded?).to eq(true)
|
|
end
|
|
end
|
|
|
|
describe '#error_message' do
|
|
it 'returns the error message to display when the threshold is exceeded' do
|
|
transaction = described_class.new
|
|
transaction.count = max = described_class::THRESHOLD
|
|
|
|
expect(transaction.error_message).to eq(
|
|
"Too many SQL queries were executed: a maximum of #{max} " \
|
|
"is allowed but #{max} SQL queries were executed"
|
|
)
|
|
end
|
|
|
|
it 'includes the action name in the error message when present' do
|
|
transaction = described_class.new
|
|
transaction.count = max = described_class::THRESHOLD
|
|
transaction.action = 'UsersController#show'
|
|
|
|
expect(transaction.error_message).to eq(
|
|
"Too many SQL queries were executed in UsersController#show: " \
|
|
"a maximum of #{max} is allowed but #{max} SQL queries were executed"
|
|
)
|
|
end
|
|
end
|
|
end
|