diff options
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.rb | 95 |
1 files changed, 81 insertions, 14 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 c4364826ee2..7338ea657b9 100644 --- a/spec/lib/gitlab/database/background_migration/batched_job_spec.rb +++ b/spec/lib/gitlab/database/background_migration/batched_job_spec.rb @@ -7,18 +7,85 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedJob, type: :model d 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) } + end + + describe 'state machine' do + let_it_be(:job) { create(:batched_background_migration_job, :failed) } + + 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 } ) + + expect { job.run! }.to change(job, :started_at) + end + end + + context 'when a job succeed' do + let(:job) { create(:batched_background_migration_job, :running) } + + it 'logs the transition' do + expect(Gitlab::AppLogger).to receive(:info).with( { batched_job_id: job.id, message: 'BatchedJob transition', new_state: :succeeded, previous_state: :running } ) + + job.succeed! + end + + it 'updates the finished_at' do + expect { job.succeed! }.to change(job, :finished_at).from(nil).to(Time) + end + + it 'creates a new transition log' do + job.succeed! + + transition_log = job.batched_job_transition_logs.first + + expect(transition_log.next_status).to eq('succeeded') + expect(transition_log.exception_class).to be_nil + expect(transition_log.exception_message).to be_nil + end + end + + context 'when a job fails' do + let(:job) { create(:batched_background_migration_job, :running) } + + it 'logs the transition' do + expect(Gitlab::AppLogger).to receive(:info).with( { batched_job_id: job.id, message: 'BatchedJob transition', new_state: :failed, previous_state: :running } ) + + job.failure! + end + + it 'tracks the exception' do + expect(Gitlab::ErrorTracking).to receive(:track_exception).with(RuntimeError, { batched_job_id: job.id } ) + + job.failure!(error: RuntimeError.new) + end + + it 'updates the finished_at' do + expect { job.failure! }.to change(job, :finished_at).from(nil).to(Time) + end + + it 'creates a new transition log' do + job.failure!(error: RuntimeError.new) + + transition_log = job.batched_job_transition_logs.first + + expect(transition_log.next_status).to eq('failed') + expect(transition_log.exception_class).to eq('RuntimeError') + expect(transition_log.exception_message).to eq('RuntimeError') + end + end end describe 'scopes' do let_it_be(:fixed_time) { Time.new(2021, 04, 27, 10, 00, 00, 00) } - let_it_be(:pending_job) { create(:batched_background_migration_job, status: :pending, updated_at: fixed_time) } - let_it_be(:running_job) { create(:batched_background_migration_job, status: :running, updated_at: fixed_time) } - let_it_be(:stuck_job) { create(:batched_background_migration_job, status: :pending, updated_at: fixed_time - described_class::STUCK_JOBS_TIMEOUT) } - let_it_be(:failed_job) { create(:batched_background_migration_job, status: :failed, attempts: 1) } + let_it_be(:pending_job) { create(:batched_background_migration_job, :pending, updated_at: fixed_time) } + let_it_be(:running_job) { create(:batched_background_migration_job, :running, updated_at: fixed_time) } + let_it_be(:stuck_job) { create(:batched_background_migration_job, :pending, updated_at: fixed_time - described_class::STUCK_JOBS_TIMEOUT) } + let_it_be(:failed_job) { create(:batched_background_migration_job, :failed, attempts: 1) } - let!(:max_attempts_failed_job) { create(:batched_background_migration_job, status: :failed, attempts: described_class::MAX_ATTEMPTS) } - let!(:succeeded_job) { create(:batched_background_migration_job, status: :succeeded) } + let!(:max_attempts_failed_job) { create(:batched_background_migration_job, :failed, attempts: described_class::MAX_ATTEMPTS) } + let!(:succeeded_job) { create(:batched_background_migration_job, :succeeded) } before do travel_to fixed_time @@ -82,10 +149,10 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedJob, type: :model d subject { job.time_efficiency } let(:migration) { build(:batched_background_migration, interval: 120.seconds) } - let(:job) { build(:batched_background_migration_job, status: :succeeded, batched_migration: migration) } + let(:job) { build(:batched_background_migration_job, :succeeded, batched_migration: migration) } context 'when job has not yet succeeded' do - let(:job) { build(:batched_background_migration_job, status: :running) } + let(:job) { build(:batched_background_migration_job, :running) } it 'returns nil' do expect(subject).to be_nil @@ -130,7 +197,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedJob, type: :model d end describe '#split_and_retry!' do - let!(:job) { create(:batched_background_migration_job, batch_size: 10, min_value: 6, max_value: 15, status: :failed, attempts: 3) } + let!(:job) { create(:batched_background_migration_job, :failed, batch_size: 10, min_value: 6, max_value: 15, attempts: 3) } context 'when job can be split' do before do @@ -146,7 +213,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedJob, type: :model d min_value: 6, max_value: 10, batch_size: 5, - status: 'failed', + status_name: :failed, attempts: 0, started_at: nil, finished_at: nil, @@ -160,7 +227,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedJob, type: :model d min_value: 11, max_value: 15, batch_size: 5, - status: 'failed', + status_name: :failed, attempts: 0, started_at: nil, finished_at: nil, @@ -177,7 +244,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedJob, type: :model d end context 'when job is not failed' do - let!(:job) { create(:batched_background_migration_job, status: :succeeded) } + let!(:job) { create(:batched_background_migration_job, :succeeded) } it 'raises an exception' do expect { job.split_and_retry! }.to raise_error 'Only failed jobs can be split' @@ -185,7 +252,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedJob, type: :model d end context 'when batch size is already 1' do - let!(:job) { create(:batched_background_migration_job, batch_size: 1, status: :failed) } + let!(:job) { create(:batched_background_migration_job, :failed, batch_size: 1) } it 'raises an exception' do expect { job.split_and_retry! }.to raise_error 'Job cannot be split further' @@ -204,7 +271,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedJob, type: :model d expect(job.batch_size).to eq(5) expect(job.attempts).to eq(0) - expect(job.status).to eq('failed') + expect(job.status_name).to eq(:failed) end end end |