Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/lib/gitlab/database/background_migration/batched_job_spec.rb')
-rw-r--r--spec/lib/gitlab/database/background_migration/batched_job_spec.rb112
1 files changed, 103 insertions, 9 deletions
diff --git a/spec/lib/gitlab/database/background_migration/batched_job_spec.rb b/spec/lib/gitlab/database/background_migration/batched_job_spec.rb
index 7338ea657b9..8c663ff9f8a 100644
--- a/spec/lib/gitlab/database/background_migration/batched_job_spec.rb
+++ b/spec/lib/gitlab/database/background_migration/batched_job_spec.rb
@@ -5,6 +5,10 @@ require 'spec_helper'
RSpec.describe Gitlab::Database::BackgroundMigration::BatchedJob, type: :model do
it_behaves_like 'having unique enum values'
+ it { is_expected.to be_a Gitlab::Database::SharedModel }
+
+ it { expect(described_class::TIMEOUT_EXCEPTIONS).to match_array [ActiveRecord::StatementTimeout, ActiveRecord::ConnectionTimeoutError, ActiveRecord::AdapterTimeout, ActiveRecord::LockWaitTimeout] }
+
describe 'associations' do
it { is_expected.to belong_to(:batched_migration).with_foreign_key(:batched_background_migration_id) }
it { is_expected.to have_many(:batched_job_transition_logs).with_foreign_key(:batched_background_migration_job_id) }
@@ -13,6 +17,8 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedJob, type: :model d
describe 'state machine' do
let_it_be(:job) { create(:batched_background_migration_job, :failed) }
+ it { expect(described_class.state_machine.states.map(&:name)).to eql(%i(pending running failed succeeded)) }
+
context 'when a job is running' do
it 'logs the transition' do
expect(Gitlab::AppLogger).to receive(:info).with( { batched_job_id: job.id, message: 'BatchedJob transition', new_state: :running, previous_state: :failed } )
@@ -45,6 +51,51 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedJob, type: :model d
end
end
+ context 'when a job fails the number of max times' do
+ let(:max_times) { described_class::MAX_ATTEMPTS }
+ let!(:job) { create(:batched_background_migration_job, :running, batch_size: 10, min_value: 6, max_value: 15, attempts: max_times) }
+
+ context 'when job can be split' do
+ let(:exception) { ActiveRecord::StatementTimeout.new('Timeout!') }
+
+ before do
+ allow_next_instance_of(Gitlab::BackgroundMigration::BatchingStrategies::PrimaryKeyBatchingStrategy) do |batch_class|
+ allow(batch_class).to receive(:next_batch).and_return([6, 10])
+ end
+ end
+
+ it 'splits the job into two retriable jobs' do
+ expect { job.failure!(error: exception) }.to change { job.batched_migration.batched_jobs.retriable.count }.from(0).to(2)
+ end
+ end
+
+ context 'when the job cannot be split' do
+ let(:exception) { ActiveRecord::StatementTimeout.new('Timeout!') }
+ let(:max_times) { described_class::MAX_ATTEMPTS }
+ let!(:job) { create(:batched_background_migration_job, :running, batch_size: 50, sub_batch_size: 20, min_value: 6, max_value: 15, attempts: max_times) }
+ let(:error_message) { 'Job cannot be split further' }
+ let(:split_and_retry_exception) { Gitlab::Database::BackgroundMigration::SplitAndRetryError.new(error_message) }
+
+ before do
+ allow(job).to receive(:split_and_retry!).and_raise(split_and_retry_exception)
+ end
+
+ it 'does not split the job' do
+ expect { job.failure!(error: exception) }.not_to change { job.batched_migration.batched_jobs.retriable.count }
+ end
+
+ it 'keeps the same job attributes' do
+ expect { job.failure!(error: exception) }.not_to change { job }
+ end
+
+ it 'logs the error' do
+ expect(Gitlab::AppLogger).to receive(:error).with( { message: error_message, batched_job_id: job.id } )
+
+ job.failure!(error: exception)
+ end
+ end
+ end
+
context 'when a job fails' do
let(:job) { create(:batched_background_migration_job, :running) }
@@ -145,6 +196,49 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedJob, type: :model d
end
end
+ describe '#can_split?' do
+ subject { job.can_split?(exception) }
+
+ context 'when the number of attempts is greater than the limit and the batch_size is greater than the sub_batch_size' do
+ let(:job) { create(:batched_background_migration_job, :failed, batch_size: 4, sub_batch_size: 2, attempts: described_class::MAX_ATTEMPTS + 1) }
+
+ context 'when is a timeout exception' do
+ let(:exception) { ActiveRecord::StatementTimeout.new }
+
+ it { expect(subject).to be_truthy }
+ end
+
+ context 'when is not a timeout exception' do
+ let(:exception) { RuntimeError.new }
+
+ it { expect(subject).to be_falsey }
+ end
+ end
+
+ context 'when the number of attempts is lower than the limit and the batch_size is greater than the sub_batch_size' do
+ let(:job) { create(:batched_background_migration_job, :failed, batch_size: 4, sub_batch_size: 2, attempts: described_class::MAX_ATTEMPTS - 1) }
+
+ context 'when is a timeout exception' do
+ let(:exception) { ActiveRecord::StatementTimeout.new }
+
+ it { expect(subject).to be_falsey }
+ end
+
+ context 'when is not a timeout exception' do
+ let(:exception) { RuntimeError.new }
+
+ it { expect(subject).to be_falsey }
+ end
+ end
+
+ context 'when the batch_size is lower than the sub_batch_size' do
+ let(:job) { create(:batched_background_migration_job, :failed, batch_size: 2, sub_batch_size: 4) }
+ let(:exception) { ActiveRecord::StatementTimeout.new }
+
+ it { expect(subject).to be_falsey }
+ end
+ end
+
describe '#time_efficiency' do
subject { job.time_efficiency }
@@ -197,15 +291,17 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedJob, type: :model d
end
describe '#split_and_retry!' do
- let!(:job) { create(:batched_background_migration_job, :failed, batch_size: 10, min_value: 6, max_value: 15, attempts: 3) }
+ let_it_be(:migration) { create(:batched_background_migration, table_name: :events) }
+ let_it_be(:job) { create(:batched_background_migration_job, :failed, batched_migration: migration, batch_size: 10, min_value: 6, max_value: 15, attempts: 3) }
+ let_it_be(:project) { create(:project) }
- context 'when job can be split' do
- before do
- allow_next_instance_of(Gitlab::BackgroundMigration::BatchingStrategies::PrimaryKeyBatchingStrategy) do |batch_class|
- allow(batch_class).to receive(:next_batch).with(anything, anything, batch_min_value: 6, batch_size: 5).and_return([6, 10])
- end
+ before_all do
+ (6..16).each do |id|
+ create(:event, id: id, project: project)
end
+ end
+ context 'when job can be split' do
it 'sets the correct attributes' do
expect { job.split_and_retry! }.to change { described_class.count }.by(1)
@@ -261,9 +357,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedJob, type: :model d
context 'when computed midpoint is larger than the max value of the batch' do
before do
- allow_next_instance_of(Gitlab::BackgroundMigration::BatchingStrategies::PrimaryKeyBatchingStrategy) do |batch_class|
- allow(batch_class).to receive(:next_batch).with(anything, anything, batch_min_value: 6, batch_size: 5).and_return([6, 16])
- end
+ Event.where(id: 6..12).delete_all
end
it 'lowers the batch size and resets the number of attempts' do