diff options
Diffstat (limited to 'spec/services/loose_foreign_keys/batch_cleaner_service_spec.rb')
-rw-r--r-- | spec/services/loose_foreign_keys/batch_cleaner_service_spec.rb | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/spec/services/loose_foreign_keys/batch_cleaner_service_spec.rb b/spec/services/loose_foreign_keys/batch_cleaner_service_spec.rb index d3d57ea2444..538d9638879 100644 --- a/spec/services/loose_foreign_keys/batch_cleaner_service_spec.rb +++ b/spec/services/loose_foreign_keys/batch_cleaner_service_spec.rb @@ -115,4 +115,82 @@ RSpec.describe LooseForeignKeys::BatchCleanerService do expect(loose_fk_child_table_2.where(parent_id_with_different_column: other_parent_record.id).count).to eq(2) end end + + describe 'fair queueing' do + context 'when the execution is over the limit' do + let(:modification_tracker) { instance_double(LooseForeignKeys::ModificationTracker) } + let(:over_limit_return_values) { [true] } + let(:deleted_record) { LooseForeignKeys::DeletedRecord.load_batch_for_table('public._test_loose_fk_parent_table', 1).first } + let(:deleted_records_rescheduled_counter) { Gitlab::Metrics.registry.get(:loose_foreign_key_rescheduled_deleted_records) } + let(:deleted_records_incremented_counter) { Gitlab::Metrics.registry.get(:loose_foreign_key_incremented_deleted_records) } + + let(:cleaner) do + described_class.new(parent_table: '_test_loose_fk_parent_table', + loose_foreign_key_definitions: loose_foreign_key_definitions, + deleted_parent_records: LooseForeignKeys::DeletedRecord.load_batch_for_table('public._test_loose_fk_parent_table', 100), + modification_tracker: modification_tracker + ) + end + + before do + parent_record_1.delete + allow(modification_tracker).to receive(:over_limit?).and_return(*over_limit_return_values) + allow(modification_tracker).to receive(:add_deletions) + end + + context 'when the deleted record is under the maximum allowed cleanup attempts' do + it 'updates the cleanup_attempts column', :aggregate_failures do + deleted_record.update!(cleanup_attempts: 1) + + cleaner.execute + + expect(deleted_record.reload.cleanup_attempts).to eq(2) + expect(deleted_records_incremented_counter.get(table: loose_fk_parent_table.table_name, db_config_name: 'main')).to eq(1) + end + + context 'when the deleted record is above the maximum allowed cleanup attempts' do + it 'reschedules the record', :aggregate_failures do + deleted_record.update!(cleanup_attempts: LooseForeignKeys::BatchCleanerService::CLEANUP_ATTEMPTS_BEFORE_RESCHEDULE + 1) + + freeze_time do + cleaner.execute + + expect(deleted_record.reload).to have_attributes( + cleanup_attempts: 0, + consume_after: 5.minutes.from_now + ) + expect(deleted_records_rescheduled_counter.get(table: loose_fk_parent_table.table_name, db_config_name: 'main')).to eq(1) + end + end + end + + describe 'when over limit happens on the second cleanup call without skip locked' do + # over_limit? is called twice, we test here the 2nd call + # - When invoking cleanup with SKIP LOCKED + # - When invoking cleanup (no SKIP LOCKED) + let(:over_limit_return_values) { [false, true] } + + it 'updates the cleanup_attempts column' do + expect(cleaner).to receive(:run_cleaner_service).twice + + deleted_record.update!(cleanup_attempts: 1) + + cleaner.execute + + expect(deleted_record.reload.cleanup_attempts).to eq(2) + end + end + end + + context 'when the lfk_fair_queueing FF is off' do + before do + stub_feature_flags(lfk_fair_queueing: false) + end + + it 'does nothing' do + expect { cleaner.execute }.not_to change { deleted_record.reload.cleanup_attempts } + end + end + end + end end |