Class: Gitlab::Database::BackgroundMigration::BatchedMigrationRunner

Inherits:
Object
  • Object
show all
Defined in:
lib/gitlab/database/background_migration/batched_migration_runner.rb

Constant Summary collapse

FailedToFinalize =
Class.new(RuntimeError)

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(connection:, migration_wrapper: BatchedMigrationWrapper.new(connection: connection)) ⇒ BatchedMigrationRunner

Returns a new instance of BatchedMigrationRunner.



13
14
15
16
# File 'lib/gitlab/database/background_migration/batched_migration_runner.rb', line 13

def initialize(connection:, migration_wrapper: BatchedMigrationWrapper.new(connection: connection))
  @connection = connection
  @migration_wrapper = migration_wrapper
end

Class Method Details

.finalize(job_class_name, table_name, column_name, job_arguments, connection:) ⇒ Object



9
10
11
# File 'lib/gitlab/database/background_migration/batched_migration_runner.rb', line 9

def self.finalize(job_class_name, table_name, column_name, job_arguments, connection:)
  new(connection: connection).finalize(job_class_name, table_name, column_name, job_arguments)
end

Instance Method Details

#finalize(job_class_name, table_name, column_name, job_arguments) ⇒ Object

Finalize migration for given configuration.

If the migration is already finished, do nothing. Otherwise change its status to ‘finalizing` in order to prevent it being picked up by the background worker. Perform all pending jobs, then keep running until migration is finished.



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
# File 'lib/gitlab/database/background_migration/batched_migration_runner.rb', line 57

def finalize(job_class_name, table_name, column_name, job_arguments)
  migration = BatchedMigration.find_for_configuration(
    Gitlab::Database.gitlab_schemas_for_connection(connection),
    job_class_name, table_name, column_name, job_arguments
  )

  configuration = {
    job_class_name: job_class_name,
    table_name: table_name,
    column_name: column_name,
    job_arguments: job_arguments
  }

  if migration.nil?
    Gitlab::AppLogger.warn "Could not find batched background migration for the given configuration: #{configuration}"
  elsif migration.finished?
    Gitlab::AppLogger.warn "Batched background migration for the given configuration is already finished: #{configuration}"
  else
    migration.reset_attempts_of_blocked_jobs!

    migration.finalize!
    migration.batched_jobs.with_status(:pending).each { |job| migration_wrapper.perform(job) }

    run_migration_while(migration, :finalizing)

    error_message = "Batched migration #{migration.job_class_name} could not be completed and a manual action is required."\
                    "Check the admin panel at (`/admin/background_migrations`) for more details."

    raise FailedToFinalize, error_message unless migration.finished?
  end
end

#run_entire_migration(migration) ⇒ Object

Runs all remaining batched_jobs for a batched_background_migration.

This method is intended to be used in a test/dev environment to execute the background migration inline. It should NOT be used in a real environment for any non-trivial migrations.



44
45
46
47
48
49
50
# File 'lib/gitlab/database/background_migration/batched_migration_runner.rb', line 44

def run_entire_migration(migration)
  unless Rails.env.development? || Rails.env.test?
    raise 'this method is not intended for use in real environments'
  end

  run_migration_while(migration, :active)
end

#run_migration_job(active_migration) ⇒ Object

Runs the next batched_job for a batched_background_migration.

The batch bounds of the next job are calculated at runtime, based on the migration configuration and the bounds of the most recently created batched_job. Updating the migration configuration will cause future jobs to use the updated batch sizes.

The job instance will automatically receive a set of arguments based on the migration configuration. For more details, see the BatchedMigrationWrapper class.

Note that this method is primarily intended to called by a scheduled worker.



28
29
30
31
32
33
34
35
36
37
38
# File 'lib/gitlab/database/background_migration/batched_migration_runner.rb', line 28

def run_migration_job(active_migration)
  if next_batched_job = find_or_create_next_batched_job(active_migration)
    migration_wrapper.perform(next_batched_job)

    adjust_migration(active_migration)

    active_migration.failure! if next_batched_job.failed? && active_migration.should_stop?
  else
    finish_active_migration(active_migration)
  end
end