diff options
Diffstat (limited to 'spec/lib/gitlab/database/migrations/batched_background_migration_helpers_spec.rb')
-rw-r--r-- | spec/lib/gitlab/database/migrations/batched_background_migration_helpers_spec.rb | 216 |
1 files changed, 199 insertions, 17 deletions
diff --git a/spec/lib/gitlab/database/migrations/batched_background_migration_helpers_spec.rb b/spec/lib/gitlab/database/migrations/batched_background_migration_helpers_spec.rb index d1a66036149..f3414727245 100644 --- a/spec/lib/gitlab/database/migrations/batched_background_migration_helpers_spec.rb +++ b/spec/lib/gitlab/database/migrations/batched_background_migration_helpers_spec.rb @@ -3,8 +3,14 @@ require 'spec_helper' RSpec.describe Gitlab::Database::Migrations::BatchedBackgroundMigrationHelpers do + let(:migration_class) do + Class.new(ActiveRecord::Migration[6.1]) + .include(described_class) + .include(Gitlab::Database::Migrations::ReestablishedConnectionStack) + end + let(:migration) do - ActiveRecord::Migration.new.extend(described_class) + migration_class.new end describe '#queue_batched_background_migration' do @@ -12,6 +18,9 @@ RSpec.describe Gitlab::Database::Migrations::BatchedBackgroundMigrationHelpers d before do allow(Gitlab::Database::PgClass).to receive(:for_table).and_call_original + expect(Gitlab::Database::QueryAnalyzers::RestrictAllowedSchemas).to receive(:require_dml_mode!) + + allow(migration).to receive(:transaction_open?).and_return(false) end context 'when such migration already exists' do @@ -27,7 +36,8 @@ RSpec.describe Gitlab::Database::Migrations::BatchedBackgroundMigrationHelpers d batch_class_name: 'MyBatchClass', batch_size: 200, sub_batch_size: 20, - job_arguments: [[:id], [:id_convert_to_bigint]] + job_arguments: [[:id], [:id_convert_to_bigint]], + gitlab_schema: :gitlab_ci ) expect do @@ -41,7 +51,8 @@ RSpec.describe Gitlab::Database::Migrations::BatchedBackgroundMigrationHelpers d batch_max_value: 1000, batch_class_name: 'MyBatchClass', batch_size: 100, - sub_batch_size: 10) + sub_batch_size: 10, + gitlab_schema: :gitlab_ci) end.not_to change { Gitlab::Database::BackgroundMigration::BatchedMigration.count } end end @@ -60,7 +71,8 @@ RSpec.describe Gitlab::Database::Migrations::BatchedBackgroundMigrationHelpers d batch_class_name: 'MyBatchClass', batch_size: 100, max_batch_size: 10000, - sub_batch_size: 10) + sub_batch_size: 10, + gitlab_schema: :gitlab_ci) end.to change { Gitlab::Database::BackgroundMigration::BatchedMigration.count }.by(1) expect(Gitlab::Database::BackgroundMigration::BatchedMigration.last).to have_attributes( @@ -76,7 +88,8 @@ RSpec.describe Gitlab::Database::Migrations::BatchedBackgroundMigrationHelpers d sub_batch_size: 10, job_arguments: %w[], status_name: :active, - total_tuple_count: pgclass_info.cardinality_estimate) + total_tuple_count: pgclass_info.cardinality_estimate, + gitlab_schema: 'gitlab_ci') end context 'when the job interval is lower than the minimum' do @@ -160,6 +173,31 @@ RSpec.describe Gitlab::Database::Migrations::BatchedBackgroundMigrationHelpers d expect(Gitlab::Database::BackgroundMigration::BatchedMigration.last).to be_finished end + + context 'when within transaction' do + before do + allow(migration).to receive(:transaction_open?).and_return(true) + end + + it 'does raise an exception' do + expect { migration.queue_batched_background_migration('MyJobClass', :events, :id, job_interval: 5.minutes)} + .to raise_error /`queue_batched_background_migration` cannot be run inside a transaction./ + end + end + end + end + + context 'when gitlab_schema is not given' do + it 'fetches gitlab_schema from the migration context' do + expect(migration).to receive(:gitlab_schema_from_context).and_return(:gitlab_ci) + + expect do + migration.queue_batched_background_migration('MyJobClass', :events, :id, job_interval: 5.minutes) + end.to change { Gitlab::Database::BackgroundMigration::BatchedMigration.count }.by(1) + + created_migration = Gitlab::Database::BackgroundMigration::BatchedMigration.last + + expect(created_migration.gitlab_schema).to eq('gitlab_ci') end end end @@ -167,6 +205,12 @@ RSpec.describe Gitlab::Database::Migrations::BatchedBackgroundMigrationHelpers d describe '#finalize_batched_background_migration' do let!(:batched_migration) { create(:batched_background_migration, job_class_name: 'MyClass', table_name: :projects, column_name: :id, job_arguments: []) } + before do + expect(Gitlab::Database::QueryAnalyzers::RestrictAllowedSchemas).to receive(:require_dml_mode!) + + allow(migration).to receive(:transaction_open?).and_return(false) + end + it 'finalizes the migration' do allow_next_instance_of(Gitlab::Database::BackgroundMigration::BatchedMigrationRunner) do |runner| expect(runner).to receive(:finalize).with('MyClass', :projects, :id, []) @@ -183,24 +227,162 @@ RSpec.describe Gitlab::Database::Migrations::BatchedBackgroundMigrationHelpers d end end - context 'when uses a CI connection', :reestablished_active_record_base do + context 'when within transaction' do before do - skip_if_multiple_databases_not_setup + allow(migration).to receive(:transaction_open?).and_return(true) + end - ActiveRecord::Base.establish_connection(:ci) # rubocop:disable Database/EstablishConnection + it 'does raise an exception' do + expect { migration.finalize_batched_background_migration(job_class_name: 'MyJobClass', table_name: :projects, column_name: :id, job_arguments: []) } + .to raise_error /`finalize_batched_background_migration` cannot be run inside a transaction./ end + end - it 'raises an exception' do - ci_migration = create(:batched_background_migration, :active) + context 'when running migration in reconfigured ActiveRecord::Base context' do + it_behaves_like 'reconfigures connection stack', 'ci' do + before do + create(:batched_background_migration, + job_class_name: 'Ci::MyClass', + table_name: :ci_builds, + column_name: :id, + job_arguments: [], + gitlab_schema: :gitlab_ci) + end + + context 'when restrict_gitlab_migration is set to gitlab_ci' do + it 'finalizes the migration' do + migration_class.include(Gitlab::Database::MigrationHelpers::RestrictGitlabSchema) + migration_class.restrict_gitlab_migration gitlab_schema: :gitlab_ci + + allow_next_instance_of(Gitlab::Database::BackgroundMigration::BatchedMigrationRunner) do |runner| + expect(runner).to receive(:finalize).with('Ci::MyClass', :ci_builds, :id, []) do + validate_connections_stack! + end + end + + migration.finalize_batched_background_migration( + job_class_name: 'Ci::MyClass', table_name: :ci_builds, column_name: :id, job_arguments: []) + end + end + + context 'when restrict_gitlab_migration is set to gitlab_main' do + it 'does not find any migrations' do + migration_class.include(Gitlab::Database::MigrationHelpers::RestrictGitlabSchema) + migration_class.restrict_gitlab_migration gitlab_schema: :gitlab_main + + expect do + migration.finalize_batched_background_migration( + job_class_name: 'Ci::MyClass', table_name: :ci_builds, column_name: :id, job_arguments: []) + end.to raise_error /Could not find batched background migration/ + end + end + + context 'when no restrict is set' do + it 'does not find any migrations' do + expect do + migration.finalize_batched_background_migration( + job_class_name: 'Ci::MyClass', table_name: :ci_builds, column_name: :id, job_arguments: []) + end.to raise_error /Could not find batched background migration/ + end + end + end + end + + context 'when within transaction' do + before do + allow(migration).to receive(:transaction_open?).and_return(true) + end + + it 'does raise an exception' do + expect { migration.finalize_batched_background_migration(job_class_name: 'MyJobClass', table_name: :projects, column_name: :id, job_arguments: []) } + .to raise_error /`finalize_batched_background_migration` cannot be run inside a transaction./ + end + end + end + + describe '#delete_batched_background_migration' do + let(:transaction_open) { false } + + before do + expect(Gitlab::Database::QueryAnalyzers::RestrictAllowedSchemas).to receive(:require_dml_mode!) + + allow(migration).to receive(:transaction_open?).and_return(transaction_open) + end + + context 'when migration exists' do + it 'deletes it' do + create( + :batched_background_migration, + job_class_name: 'MyJobClass', + table_name: :projects, + column_name: :id, + interval: 10.minutes, + min_value: 5, + max_value: 1005, + batch_class_name: 'MyBatchClass', + batch_size: 200, + sub_batch_size: 20, + job_arguments: [[:id], [:id_convert_to_bigint]] + ) expect do - migration.finalize_batched_background_migration( - job_class_name: ci_migration.job_class_name, - table_name: ci_migration.table_name, - column_name: ci_migration.column_name, - job_arguments: ci_migration.job_arguments - ) - end.to raise_error /is currently not supported when running in decomposed/ + migration.delete_batched_background_migration( + 'MyJobClass', + :projects, + :id, + [[:id], [:id_convert_to_bigint]]) + end.to change { Gitlab::Database::BackgroundMigration::BatchedMigration.count }.from(1).to(0) + end + end + + context 'when migration does not exist' do + it 'does nothing' do + create( + :batched_background_migration, + job_class_name: 'SomeOtherJobClass', + table_name: :projects, + column_name: :id, + interval: 10.minutes, + min_value: 5, + max_value: 1005, + batch_class_name: 'MyBatchClass', + batch_size: 200, + sub_batch_size: 20, + job_arguments: [[:id], [:id_convert_to_bigint]] + ) + + expect do + migration.delete_batched_background_migration( + 'MyJobClass', + :projects, + :id, + [[:id], [:id_convert_to_bigint]]) + end.not_to change { Gitlab::Database::BackgroundMigration::BatchedMigration.count } + end + end + + context 'when within transaction' do + let(:transaction_open) { true } + + it 'raises an exception' do + expect { migration.delete_batched_background_migration('MyJobClass', :projects, :id, [[:id], [:id_convert_to_bigint]]) } + .to raise_error /`#delete_batched_background_migration` cannot be run inside a transaction./ + end + end + end + + describe '#gitlab_schema_from_context' do + context 'when allowed_gitlab_schemas is not available' do + it 'defaults to :gitlab_main' do + expect(migration.gitlab_schema_from_context).to eq(:gitlab_main) + end + end + + context 'when allowed_gitlab_schemas is available' do + it 'uses schema from allowed_gitlab_schema' do + expect(migration).to receive(:allowed_gitlab_schemas).and_return([:gitlab_ci]) + + expect(migration.gitlab_schema_from_context).to eq(:gitlab_ci) end end end |