diff options
Diffstat (limited to 'lib/gitlab/database/migrations')
9 files changed, 65 insertions, 27 deletions
diff --git a/lib/gitlab/database/migrations/background_migration_helpers.rb b/lib/gitlab/database/migrations/background_migration_helpers.rb index 28491a934a0..19d80ba1d64 100644 --- a/lib/gitlab/database/migrations/background_migration_helpers.rb +++ b/lib/gitlab/database/migrations/background_migration_helpers.rb @@ -264,6 +264,34 @@ module Gitlab migration end + # Force a background migration to complete. + # + # WARNING: This method will block the caller and move the background migration from an + # asynchronous migration to a synchronous migration. + # + # 1. Steal work from sidekiq and perform immediately (avoid duplicates generated by step 2). + # 2. Process any pending tracked jobs. + # 3. Steal work from sidekiq and perform immediately (clear anything left from step 2). + # 4. Optionally remove job tracking information. + # + # This method does not garauntee that all jobs completed successfully. + def finalize_background_migration(class_name, delete_tracking_jobs: ['succeeded']) + # Empty the sidekiq queue. + Gitlab::BackgroundMigration.steal(class_name) + + # Process pending tracked jobs. + jobs = Gitlab::Database::BackgroundMigrationJob.pending.for_migration_class(class_name) + jobs.find_each do |job| + BackgroundMigrationWorker.new.perform(job.class_name, job.arguments) + end + + # Empty the sidekiq queue. + Gitlab::BackgroundMigration.steal(class_name) + + # Delete job tracking rows. + delete_job_tracking(class_name, status: delete_tracking_jobs) if delete_tracking_jobs + end + def perform_background_migration_inline? Rails.env.test? || Rails.env.development? end @@ -304,6 +332,12 @@ module Gitlab end end + def delete_job_tracking(class_name, status: 'succeeded') + status = Array(status).map { |s| Gitlab::Database::BackgroundMigrationJob.statuses[s] } + jobs = Gitlab::Database::BackgroundMigrationJob.where(status: status).for_migration_class(class_name) + jobs.each_batch { |batch| batch.delete_all } + end + private def track_in_database(class_name, arguments) diff --git a/lib/gitlab/database/migrations/instrumentation.rb b/lib/gitlab/database/migrations/instrumentation.rb index e9ef80d5198..d1e55eb825c 100644 --- a/lib/gitlab/database/migrations/instrumentation.rb +++ b/lib/gitlab/database/migrations/instrumentation.rb @@ -9,18 +9,20 @@ module Gitlab attr_reader :observations - def initialize(observers = ::Gitlab::Database::Migrations::Observers.all_observers) - @observers = observers + def initialize(observer_classes = ::Gitlab::Database::Migrations::Observers.all_observers) + @observer_classes = observer_classes @observations = [] end - def observe(migration, &block) - observation = Observation.new(migration) + def observe(version:, name:, &block) + observation = Observation.new(version, name) observation.success = true + observers = observer_classes.map { |c| c.new(observation) } + exception = nil - on_each_observer { |observer| observer.before } + on_each_observer(observers) { |observer| observer.before } observation.walltime = Benchmark.realtime do yield @@ -29,8 +31,8 @@ module Gitlab observation.success = false end - on_each_observer { |observer| observer.after } - on_each_observer { |observer| observer.record(observation) } + on_each_observer(observers) { |observer| observer.after } + on_each_observer(observers) { |observer| observer.record } record_observation(observation) @@ -41,13 +43,13 @@ module Gitlab private - attr_reader :observers + attr_reader :observer_classes def record_observation(observation) @observations << observation end - def on_each_observer(&block) + def on_each_observer(observers, &block) observers.each do |observer| yield observer rescue StandardError => e diff --git a/lib/gitlab/database/migrations/observation.rb b/lib/gitlab/database/migrations/observation.rb index 046843824a4..54eedec3c7b 100644 --- a/lib/gitlab/database/migrations/observation.rb +++ b/lib/gitlab/database/migrations/observation.rb @@ -4,7 +4,8 @@ module Gitlab module Database module Migrations Observation = Struct.new( - :migration, + :version, + :name, :walltime, :success, :total_database_size_change, diff --git a/lib/gitlab/database/migrations/observers.rb b/lib/gitlab/database/migrations/observers.rb index 979a098d699..140b3feed64 100644 --- a/lib/gitlab/database/migrations/observers.rb +++ b/lib/gitlab/database/migrations/observers.rb @@ -6,10 +6,10 @@ module Gitlab module Observers def self.all_observers [ - TotalDatabaseSizeChange.new, - QueryStatistics.new, - QueryLog.new, - QueryDetails.new + TotalDatabaseSizeChange, + QueryStatistics, + QueryLog, + QueryDetails ] end end diff --git a/lib/gitlab/database/migrations/observers/migration_observer.rb b/lib/gitlab/database/migrations/observers/migration_observer.rb index 9bfbf35887d..85d18abb9ef 100644 --- a/lib/gitlab/database/migrations/observers/migration_observer.rb +++ b/lib/gitlab/database/migrations/observers/migration_observer.rb @@ -5,10 +5,11 @@ module Gitlab module Migrations module Observers class MigrationObserver - attr_reader :connection + attr_reader :connection, :observation - def initialize + def initialize(observation) @connection = ActiveRecord::Base.connection + @observation = observation end def before @@ -19,7 +20,7 @@ module Gitlab # implement in subclass end - def record(observation) + def record raise NotImplementedError, 'implement in subclass' end end diff --git a/lib/gitlab/database/migrations/observers/query_details.rb b/lib/gitlab/database/migrations/observers/query_details.rb index 52b6464d449..dadacd2d2fc 100644 --- a/lib/gitlab/database/migrations/observers/query_details.rb +++ b/lib/gitlab/database/migrations/observers/query_details.rb @@ -6,8 +6,8 @@ module Gitlab module Observers class QueryDetails < MigrationObserver def before - @file_path = File.join(Instrumentation::RESULT_DIR, 'current-details.json') - @file = File.open(@file_path, 'wb') + file_path = File.join(Instrumentation::RESULT_DIR, "#{observation.version}_#{observation.name}-query-details.json") + @file = File.open(file_path, 'wb') @writer = Oj::StreamWriter.new(@file, {}) @writer.push_array @subscriber = ActiveSupport::Notifications.subscribe('sql.active_record') do |*args| @@ -22,8 +22,8 @@ module Gitlab @file.close end - def record(observation) - File.rename(@file_path, File.join(Instrumentation::RESULT_DIR, "#{observation.migration}-query-details.json")) + def record + # no-op end def record_sql_event(_name, started, finished, _unique_id, payload) diff --git a/lib/gitlab/database/migrations/observers/query_log.rb b/lib/gitlab/database/migrations/observers/query_log.rb index 45df07fe391..e15d733d2a2 100644 --- a/lib/gitlab/database/migrations/observers/query_log.rb +++ b/lib/gitlab/database/migrations/observers/query_log.rb @@ -7,8 +7,8 @@ module Gitlab class QueryLog < MigrationObserver def before @logger_was = ActiveRecord::Base.logger - @log_file_path = File.join(Instrumentation::RESULT_DIR, 'current.log') - @logger = Logger.new(@log_file_path) + file_path = File.join(Instrumentation::RESULT_DIR, "#{observation.version}_#{observation.name}.log") + @logger = Logger.new(file_path) ActiveRecord::Base.logger = @logger end @@ -17,8 +17,8 @@ module Gitlab @logger.close end - def record(observation) - File.rename(@log_file_path, File.join(Instrumentation::RESULT_DIR, "#{observation.migration}.log")) + def record + # no-op end end end diff --git a/lib/gitlab/database/migrations/observers/query_statistics.rb b/lib/gitlab/database/migrations/observers/query_statistics.rb index 466f4724256..54504646a79 100644 --- a/lib/gitlab/database/migrations/observers/query_statistics.rb +++ b/lib/gitlab/database/migrations/observers/query_statistics.rb @@ -16,7 +16,7 @@ module Gitlab connection.execute('select pg_stat_statements_reset()') end - def record(observation) + def record return unless enabled? observation.query_statistics = connection.execute(<<~SQL) diff --git a/lib/gitlab/database/migrations/observers/total_database_size_change.rb b/lib/gitlab/database/migrations/observers/total_database_size_change.rb index 0b76b0bef5e..2e89498b79f 100644 --- a/lib/gitlab/database/migrations/observers/total_database_size_change.rb +++ b/lib/gitlab/database/migrations/observers/total_database_size_change.rb @@ -13,7 +13,7 @@ module Gitlab @size_after = get_total_database_size end - def record(observation) + def record return unless @size_after && @size_before observation.total_database_size_change = @size_after - @size_before |