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

execution_worker_spec.rb « batched_background_migration « database « workers « spec - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 9a850a98f2fbfddbefd7b60ec14671572fc85fc3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# frozen_string_literal: true

require 'spec_helper'

RSpec.describe Database::BatchedBackgroundMigration::ExecutionWorker, :clean_gitlab_redis_shared_state do
  include ExclusiveLeaseHelpers

  describe '#perform' do
    let(:database_name) { Gitlab::Database::MAIN_DATABASE_NAME.to_sym }
    let(:base_model) { Gitlab::Database.database_base_models[database_name] }
    let(:table_name) { :events }
    let(:job_interval) { 5.minutes }
    let(:lease_timeout) { job_interval * described_class::LEASE_TIMEOUT_MULTIPLIER }
    let(:interval_variance) { described_class::INTERVAL_VARIANCE }

    subject(:worker) { described_class.new }

    context 'when the feature flag is disabled' do
      let(:migration) do
        create(:batched_background_migration, :active, interval: job_interval, table_name: table_name)
      end

      before do
        stub_feature_flags(execute_batched_migrations_on_schedule: false)
      end

      it 'does nothing' do
        expect(Gitlab::Database::BackgroundMigration::BatchedMigration).not_to receive(:find_executable)
        expect(worker).not_to receive(:run_migration_job)

        worker.perform(database_name, migration.id)
      end
    end

    context 'when the feature flag is enabled' do
      before do
        stub_feature_flags(execute_batched_migrations_on_schedule: true)
      end

      context 'when the provided database is sharing config' do
        before do
          skip_if_multiple_databases_not_setup
        end

        it 'does nothing' do
          ci_model = Gitlab::Database.database_base_models['ci']
          expect(Gitlab::Database).to receive(:db_config_share_with)
            .with(ci_model.connection_db_config).and_return('main')

          expect(Gitlab::Database::BackgroundMigration::BatchedMigration).not_to receive(:find_executable)
          expect(worker).not_to receive(:run_migration_job)

          worker.perform(:ci, 123)
        end
      end

      context 'when migration does not exist' do
        it 'does nothing' do
          expect(worker).not_to receive(:run_migration_job)

          worker.perform(database_name, non_existing_record_id)
        end
      end

      context 'when migration exist' do
        let(:migration) do
          create(:batched_background_migration, :active, interval: job_interval, table_name: table_name)
        end

        before do
          allow(Gitlab::Database::BackgroundMigration::BatchedMigration).to receive(:find_executable)
            .with(migration.id, connection: base_model.connection)
            .and_return(migration)
        end

        context 'when the migration is no longer active' do
          it 'does not run the migration' do
            expect(Gitlab::Database::SharedModel).to receive(:using_connection).with(base_model.connection).and_yield

            expect(migration).to receive(:active?).and_return(false)

            expect(worker).not_to receive(:run_migration_job)

            worker.perform(database_name, migration.id)
          end
        end

        context 'when the interval has not elapsed' do
          it 'does not run the migration' do
            expect(Gitlab::Database::SharedModel).to receive(:using_connection).with(base_model.connection).and_yield
            expect(migration).to receive(:interval_elapsed?).with(variance: interval_variance).and_return(false)
            expect(worker).not_to receive(:run_migration_job)

            worker.perform(database_name, migration.id)
          end
        end

        context 'when the migration is still active and the interval has elapsed' do
          let(:table_name_lease_key) do
            "#{described_class.name.underscore}:database_name:#{database_name}:" \
              "table_name:#{table_name}"
          end

          context 'when can not obtain lease on the table name' do
            it 'does nothing' do
              stub_exclusive_lease_taken(table_name_lease_key, timeout: lease_timeout)

              expect(worker).not_to receive(:run_migration_job)

              worker.perform(database_name, migration.id)
            end
          end

          it 'always cleans up the exclusive lease' do
            expect_to_obtain_exclusive_lease(table_name_lease_key, 'uuid-table-name', timeout: lease_timeout)
            expect_to_cancel_exclusive_lease(table_name_lease_key, 'uuid-table-name')

            expect(worker).to receive(:run_migration_job).and_raise(RuntimeError, 'I broke')

            expect { worker.perform(database_name, migration.id) }.to raise_error(RuntimeError, 'I broke')
          end

          it 'runs the migration' do
            expect(Gitlab::Database::SharedModel).to receive(:using_connection).with(base_model.connection).and_yield

            expect_next_instance_of(Gitlab::Database::BackgroundMigration::BatchedMigrationRunner) do |instance|
              expect(instance).to receive(:run_migration_job).with(migration)
            end

            expect_to_obtain_exclusive_lease(table_name_lease_key, 'uuid-table-name', timeout: lease_timeout)
            expect_to_cancel_exclusive_lease(table_name_lease_key, 'uuid-table-name')

            expect(worker).to receive(:run_migration_job).and_call_original

            worker.perform(database_name, migration.id)
          end
        end
      end
    end
  end
end