diff options
Diffstat (limited to 'spec/lib/gitlab/database/background_migration/scheduler_spec.rb')
-rw-r--r-- | spec/lib/gitlab/database/background_migration/scheduler_spec.rb | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/spec/lib/gitlab/database/background_migration/scheduler_spec.rb b/spec/lib/gitlab/database/background_migration/scheduler_spec.rb new file mode 100644 index 00000000000..ba745acdf8a --- /dev/null +++ b/spec/lib/gitlab/database/background_migration/scheduler_spec.rb @@ -0,0 +1,182 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Database::BackgroundMigration::Scheduler, '#perform' do + let(:scheduler) { described_class.new } + + shared_examples_for 'it has no jobs to run' do + it 'does not create and run a migration job' do + test_wrapper = double('test wrapper') + + expect(test_wrapper).not_to receive(:perform) + + expect do + scheduler.perform(migration_wrapper: test_wrapper) + end.not_to change { Gitlab::Database::BackgroundMigration::BatchedJob.count } + end + end + + context 'when there are no active migrations' do + let!(:migration) { create(:batched_background_migration, :finished) } + + it_behaves_like 'it has no jobs to run' + end + + shared_examples_for 'it has completed the migration' do + it 'marks the migration as finished' do + relation = Gitlab::Database::BackgroundMigration::BatchedMigration.finished.where(id: first_migration.id) + + expect { scheduler.perform }.to change { relation.count }.by(1) + end + end + + context 'when there are active migrations' do + let!(:first_migration) { create(:batched_background_migration, :active, batch_size: 2) } + let!(:last_migration) { create(:batched_background_migration, :active) } + + let(:job_relation) do + Gitlab::Database::BackgroundMigration::BatchedJob.where(batched_background_migration_id: first_migration.id) + end + + context 'when the migration interval has not elapsed' do + before do + expect_next_found_instance_of(Gitlab::Database::BackgroundMigration::BatchedMigration) do |migration| + expect(migration).to receive(:interval_elapsed?).and_return(false) + end + end + + it_behaves_like 'it has no jobs to run' + end + + context 'when the interval has elapsed' do + before do + expect_next_found_instance_of(Gitlab::Database::BackgroundMigration::BatchedMigration) do |migration| + expect(migration).to receive(:interval_elapsed?).and_return(true) + end + end + + context 'when the first migration has no previous jobs' do + context 'when the migration has batches to process' do + let!(:event1) { create(:event) } + let!(:event2) { create(:event) } + let!(:event3) { create(:event) } + + it 'runs the job for the first batch' do + first_migration.update!(min_value: event1.id, max_value: event3.id) + + expect_next_instance_of(Gitlab::Database::BackgroundMigration::BatchedMigrationWrapper) do |wrapper| + expect(wrapper).to receive(:perform).and_wrap_original do |_, job_record| + expect(job_record).to eq(job_relation.first) + end + end + + expect { scheduler.perform }.to change { job_relation.count }.by(1) + + expect(job_relation.first).to have_attributes( + min_value: event1.id, + max_value: event2.id, + batch_size: first_migration.batch_size, + sub_batch_size: first_migration.sub_batch_size) + end + end + + context 'when the migration has no batches to process' do + it_behaves_like 'it has no jobs to run' + it_behaves_like 'it has completed the migration' + end + end + + context 'when the first migration has previous jobs' do + let!(:event1) { create(:event) } + let!(:event2) { create(:event) } + let!(:event3) { create(:event) } + + let!(:previous_job) do + create(:batched_background_migration_job, + batched_migration: first_migration, + min_value: event1.id, + max_value: event2.id, + batch_size: 2, + sub_batch_size: 1) + end + + context 'when the migration is ready to process another job' do + it 'runs the migration job for the next batch' do + first_migration.update!(min_value: event1.id, max_value: event3.id) + + expect_next_instance_of(Gitlab::Database::BackgroundMigration::BatchedMigrationWrapper) do |wrapper| + expect(wrapper).to receive(:perform).and_wrap_original do |_, job_record| + expect(job_record).to eq(job_relation.last) + end + end + + expect { scheduler.perform }.to change { job_relation.count }.by(1) + + expect(job_relation.last).to have_attributes( + min_value: event3.id, + max_value: event3.id, + batch_size: first_migration.batch_size, + sub_batch_size: first_migration.sub_batch_size) + end + end + + context 'when the migration has no batches remaining' do + let!(:final_job) do + create(:batched_background_migration_job, + batched_migration: first_migration, + min_value: event3.id, + max_value: event3.id, + batch_size: 2, + sub_batch_size: 1) + end + + it_behaves_like 'it has no jobs to run' + it_behaves_like 'it has completed the migration' + end + end + + context 'when the bounds of the next batch exceed the migration maximum value' do + let!(:events) { create_list(:event, 3) } + let(:event1) { events[0] } + let(:event2) { events[1] } + + context 'when the batch maximum exceeds the migration maximum' do + it 'clamps the batch maximum to the migration maximum' do + first_migration.update!(batch_size: 5, min_value: event1.id, max_value: event2.id) + + expect_next_instance_of(Gitlab::Database::BackgroundMigration::BatchedMigrationWrapper) do |wrapper| + expect(wrapper).to receive(:perform) + end + + expect { scheduler.perform }.to change { job_relation.count }.by(1) + + expect(job_relation.first).to have_attributes( + min_value: event1.id, + max_value: event2.id, + batch_size: first_migration.batch_size, + sub_batch_size: first_migration.sub_batch_size) + end + end + + context 'when the batch minimum exceeds the migration maximum' do + let!(:previous_job) do + create(:batched_background_migration_job, + batched_migration: first_migration, + min_value: event1.id, + max_value: event2.id, + batch_size: 5, + sub_batch_size: 1) + end + + before do + first_migration.update!(batch_size: 5, min_value: 1, max_value: event2.id) + end + + it_behaves_like 'it has no jobs to run' + it_behaves_like 'it has completed the migration' + end + end + end + end +end |