diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-08-18 11:17:02 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-08-18 11:17:02 +0300 |
commit | b39512ed755239198a9c294b6a45e65c05900235 (patch) | |
tree | d234a3efade1de67c46b9e5a38ce813627726aa7 /lib/gitlab/database | |
parent | d31474cf3b17ece37939d20082b07f6657cc79a9 (diff) |
Add latest changes from gitlab-org/gitlab@15-3-stable-eev15.3.0-rc42
Diffstat (limited to 'lib/gitlab/database')
25 files changed, 336 insertions, 35 deletions
diff --git a/lib/gitlab/database/async_indexes.rb b/lib/gitlab/database/async_indexes.rb index d89d5238356..6f301a66803 100644 --- a/lib/gitlab/database/async_indexes.rb +++ b/lib/gitlab/database/async_indexes.rb @@ -6,10 +6,16 @@ module Gitlab DEFAULT_INDEXES_PER_INVOCATION = 2 def self.create_pending_indexes!(how_many: DEFAULT_INDEXES_PER_INVOCATION) - PostgresAsyncIndex.order(:id).limit(how_many).each do |async_index| + PostgresAsyncIndex.to_create.order(:id).limit(how_many).each do |async_index| IndexCreator.new(async_index).perform end end + + def self.drop_pending_indexes!(how_many: DEFAULT_INDEXES_PER_INVOCATION) + PostgresAsyncIndex.to_drop.order(:id).limit(how_many).each do |async_index| + IndexDestructor.new(async_index).perform + end + end end end end diff --git a/lib/gitlab/database/async_indexes/index_destructor.rb b/lib/gitlab/database/async_indexes/index_destructor.rb new file mode 100644 index 00000000000..fe05872b87a --- /dev/null +++ b/lib/gitlab/database/async_indexes/index_destructor.rb @@ -0,0 +1,66 @@ +# frozen_string_literal: true + +module Gitlab + module Database + module AsyncIndexes + class IndexDestructor + include ExclusiveLeaseGuard + + TIMEOUT_PER_ACTION = 1.day + + def initialize(async_index) + @async_index = async_index + end + + def perform + try_obtain_lease do + if !index_exists? + log_index_info('Skipping dropping as the index does not exist') + else + log_index_info('Dropping async index') + + retries = Gitlab::Database::WithLockRetriesOutsideTransaction.new( + connection: connection, + timing_configuration: Gitlab::Database::Reindexing::REMOVE_INDEX_RETRY_CONFIG, + klass: self.class, + logger: Gitlab::AppLogger + ) + + retries.run(raise_on_exhaustion: false) do + connection.execute(async_index.definition) + end + + log_index_info('Finished dropping async index') + end + + async_index.destroy + end + end + + private + + attr_reader :async_index + + def index_exists? + connection.indexes(async_index.table_name).any? { |index| index.name == async_index.name } + end + + def connection + @connection ||= async_index.connection + end + + def lease_timeout + TIMEOUT_PER_ACTION + end + + def lease_key + [super, async_index.connection_db_config.name].join('/') + end + + def log_index_info(message) + Gitlab::AppLogger.info(message: message, table_name: async_index.table_name, index_name: async_index.name) + end + end + end + end +end diff --git a/lib/gitlab/database/async_indexes/migration_helpers.rb b/lib/gitlab/database/async_indexes/migration_helpers.rb index e9846dd4e85..c8f6761534c 100644 --- a/lib/gitlab/database/async_indexes/migration_helpers.rb +++ b/lib/gitlab/database/async_indexes/migration_helpers.rb @@ -77,6 +77,38 @@ module Gitlab async_index end + # Prepares an index for asynchronous destruction. + # + # Stores the index information in the postgres_async_indexes table to be removed later. The + # index will be always be removed CONCURRENTLY, so that option does not need to be given. + # + # If the requested index has already been removed, it is not stored in the table for + # asynchronous destruction. + def prepare_async_index_removal(table_name, column_name, options = {}) + index_name = options.fetch(:name) + raise 'prepare_async_index_removal must get an index name defined' if index_name.blank? + + unless index_exists?(table_name, column_name, **options) + Gitlab::AppLogger.warn "Index not removed because it does not exist (this may be due to an aborted migration or similar): table_name: #{table_name}, index_name: #{index_name}" + return + end + + definition = "DROP INDEX CONCURRENTLY #{quote_column_name(index_name)}" + + async_index = PostgresAsyncIndex.find_or_create_by!(name: index_name) do |rec| + rec.table_name = table_name + rec.definition = definition + end + + Gitlab::AppLogger.info( + message: 'Prepared index for async destruction', + table_name: async_index.table_name, + index_name: async_index.name + ) + + async_index + end + def async_index_creation_available? connection.table_exists?(:postgres_async_indexes) end diff --git a/lib/gitlab/database/async_indexes/postgres_async_index.rb b/lib/gitlab/database/async_indexes/postgres_async_index.rb index 6cb40729061..dc932482d40 100644 --- a/lib/gitlab/database/async_indexes/postgres_async_index.rb +++ b/lib/gitlab/database/async_indexes/postgres_async_index.rb @@ -13,6 +13,9 @@ module Gitlab validates :table_name, presence: true, length: { maximum: MAX_IDENTIFIER_LENGTH } validates :definition, presence: true, length: { maximum: MAX_DEFINITION_LENGTH } + scope :to_create, -> { where("definition ILIKE 'CREATE%'") } + scope :to_drop, -> { where("definition ILIKE 'DROP%'") } + def to_s definition end diff --git a/lib/gitlab/database/background_migration/batched_job.rb b/lib/gitlab/database/background_migration/batched_job.rb index 72aa1cfe00b..81898a59da7 100644 --- a/lib/gitlab/database/background_migration/batched_job.rb +++ b/lib/gitlab/database/background_migration/batched_job.rb @@ -112,7 +112,7 @@ module Gitlab end def can_split?(exception) - attempts >= MAX_ATTEMPTS && TIMEOUT_EXCEPTIONS.include?(exception&.class) && batch_size > sub_batch_size + attempts >= MAX_ATTEMPTS && TIMEOUT_EXCEPTIONS.include?(exception&.class) && batch_size > sub_batch_size && batch_size > 1 end def split_and_retry! @@ -121,7 +121,7 @@ module Gitlab new_batch_size = batch_size / 2 - raise SplitAndRetryError, 'Job cannot be split further' if new_batch_size < 1 + break update!(attempts: 0) if new_batch_size < 1 batching_strategy = batched_migration.batch_class.new(connection: self.class.connection) next_batch_bounds = batching_strategy.next_batch( diff --git a/lib/gitlab/database/background_migration/batched_migration.rb b/lib/gitlab/database/background_migration/batched_migration.rb index 9c8db2243f9..6aed1eed994 100644 --- a/lib/gitlab/database/background_migration/batched_migration.rb +++ b/lib/gitlab/database/background_migration/batched_migration.rb @@ -206,7 +206,7 @@ module Gitlab end def health_context - HealthStatus::Context.new([table_name]) + HealthStatus::Context.new(connection, [table_name]) end def hold!(until_time: 10.minutes.from_now) @@ -231,6 +231,12 @@ module Gitlab "BatchedMigration[id: #{id}]" end + def progress + return unless total_tuple_count.to_i > 0 + + 100 * migrated_tuple_count / total_tuple_count + end + private def validate_batched_jobs_status diff --git a/lib/gitlab/database/background_migration/batched_migration_runner.rb b/lib/gitlab/database/background_migration/batched_migration_runner.rb index 1bc2e931391..7224ff2b517 100644 --- a/lib/gitlab/database/background_migration/batched_migration_runner.rb +++ b/lib/gitlab/database/background_migration/batched_migration_runner.rb @@ -144,9 +144,9 @@ module Gitlab end def adjust_migration(active_migration) - signal = HealthStatus.evaluate(active_migration) + signals = HealthStatus.evaluate(active_migration) - if signal.is_a?(HealthStatus::Signals::Stop) + if signals.any?(&:stop?) active_migration.hold! else active_migration.optimize! diff --git a/lib/gitlab/database/background_migration/batched_migration_wrapper.rb b/lib/gitlab/database/background_migration/batched_migration_wrapper.rb index 5f4b2be3da8..ad747a8131d 100644 --- a/lib/gitlab/database/background_migration/batched_migration_wrapper.rb +++ b/lib/gitlab/database/background_migration/batched_migration_wrapper.rb @@ -64,9 +64,10 @@ module Gitlab batch_column: tracking_record.migration_column_name, sub_batch_size: tracking_record.sub_batch_size, pause_ms: tracking_record.pause_ms, + job_arguments: tracking_record.migration_job_arguments, connection: connection) - job_instance.perform(*tracking_record.migration_job_arguments) + job_instance.perform job_instance end diff --git a/lib/gitlab/database/background_migration/health_status.rb b/lib/gitlab/database/background_migration/health_status.rb index 01f9c5eb5fd..9a283074b32 100644 --- a/lib/gitlab/database/background_migration/health_status.rb +++ b/lib/gitlab/database/background_migration/health_status.rb @@ -4,21 +4,29 @@ module Gitlab module Database module BackgroundMigration module HealthStatus + DEFAULT_INIDICATORS = [ + Indicators::AutovacuumActiveOnTable, + Indicators::WriteAheadLog + ].freeze + # Rather than passing along the migration, we use a more explicitly defined context - Context = Struct.new(:tables) + Context = Struct.new(:connection, :tables) - def self.evaluate(migration, indicator = Indicators::AutovacuumActiveOnTable) - signal = begin - indicator.new(migration.health_context).evaluate - rescue StandardError => e - Gitlab::ErrorTracking.track_exception(e, migration_id: migration.id, - job_class_name: migration.job_class_name) - Signals::Unknown.new(indicator, reason: "unexpected error: #{e.message} (#{e.class})") - end + def self.evaluate(migration, indicators = DEFAULT_INIDICATORS) + indicators.map do |indicator| + signal = begin + indicator.new(migration.health_context).evaluate + rescue StandardError => e + Gitlab::ErrorTracking.track_exception(e, migration_id: migration.id, + job_class_name: migration.job_class_name) - log_signal(signal, migration) if signal.log_info? + Signals::Unknown.new(indicator, reason: "unexpected error: #{e.message} (#{e.class})") + end - signal + log_signal(signal, migration) if signal.log_info? + + signal + end end def self.log_signal(signal, migration) diff --git a/lib/gitlab/database/background_migration/health_status/indicators/write_ahead_log.rb b/lib/gitlab/database/background_migration/health_status/indicators/write_ahead_log.rb new file mode 100644 index 00000000000..d2fb0a8b751 --- /dev/null +++ b/lib/gitlab/database/background_migration/health_status/indicators/write_ahead_log.rb @@ -0,0 +1,74 @@ +# frozen_string_literal: true + +module Gitlab + module Database + module BackgroundMigration + module HealthStatus + module Indicators + class WriteAheadLog + include Gitlab::Utils::StrongMemoize + + LIMIT = 42 + PENDING_WAL_COUNT_SQL = <<~SQL + WITH + current_wal_file AS ( + SELECT pg_walfile_name(pg_current_wal_insert_lsn()) AS pg_walfile_name + ), + current_wal AS ( + SELECT + ('x' || substring(pg_walfile_name, 9, 8))::bit(32)::int AS log, + ('x' || substring(pg_walfile_name, 17, 8))::bit(32)::int AS seg, + pg_walfile_name + FROM current_wal_file + ), + archive_wal AS ( + SELECT + ('x' || substring(last_archived_wal, 9, 8))::bit(32)::int AS log, + ('x' || substring(last_archived_wal, 17, 8))::bit(32)::int AS seg, + last_archived_wal + FROM pg_stat_archiver + ) + SELECT ((current_wal.log - archive_wal.log) * 256) + (current_wal.seg - archive_wal.seg) AS pending_wal_count + FROM current_wal, archive_wal + SQL + + def initialize(context) + @connection = context.connection + end + + def evaluate + return Signals::NotAvailable.new(self.class, reason: 'indicator disabled') unless enabled? + + unless pending_wal_count + return Signals::NotAvailable.new(self.class, reason: 'WAL archive queue can not be calculated') + end + + if pending_wal_count > LIMIT + Signals::Stop.new(self.class, reason: "WAL archive queue is too big") + else + Signals::Normal.new(self.class, reason: 'WAL archive queue is within limit') + end + end + + private + + attr_reader :connection + + def enabled? + Feature.enabled?(:batched_migrations_health_status_wal, type: :ops) + end + + # Returns number of WAL segments pending archival + def pending_wal_count + strong_memoize(:pending_wal_count) do + Gitlab::Database::LoadBalancing::Session.current.use_primary do + connection.execute(PENDING_WAL_COUNT_SQL).to_a.first&.fetch('pending_wal_count') + end + end + end + end + end + end + end + end +end diff --git a/lib/gitlab/database/background_migration/health_status/signals.rb b/lib/gitlab/database/background_migration/health_status/signals.rb index 6cd0ebd1bd0..be741a9d91b 100644 --- a/lib/gitlab/database/background_migration/health_status/signals.rb +++ b/lib/gitlab/database/background_migration/health_status/signals.rb @@ -22,6 +22,10 @@ module Gitlab def log_info? false end + + def stop? + false + end # :nocov: private @@ -38,6 +42,10 @@ module Gitlab def log_info? true end + + def stop? + true + end # :nocov: end diff --git a/lib/gitlab/database/bulk_update.rb b/lib/gitlab/database/bulk_update.rb index b1f9da30585..d68be19047e 100644 --- a/lib/gitlab/database/bulk_update.rb +++ b/lib/gitlab/database/bulk_update.rb @@ -157,7 +157,7 @@ module Gitlab def self.execute(columns, mapping, &to_class) raise ArgumentError if mapping.blank? - entries_by_class = mapping.group_by { |k, v| block_given? ? to_class.call(k) : k.class } + entries_by_class = mapping.group_by { |k, v| to_class ? to_class.call(k) : k.class } entries_by_class.each do |model, entries| Setter.new(model, columns, entries).update! diff --git a/lib/gitlab/database/dynamic_model_helpers.rb b/lib/gitlab/database/dynamic_model_helpers.rb index ad7dea8f0d9..2deb89a0b84 100644 --- a/lib/gitlab/database/dynamic_model_helpers.rb +++ b/lib/gitlab/database/dynamic_model_helpers.rb @@ -32,7 +32,7 @@ module Gitlab def each_batch_range(table_name, connection:, scope: ->(table) { table.all }, of: BATCH_SIZE) each_batch(table_name, connection: connection, scope: scope, of: of) do |batch| - yield batch.pluck('MIN(id), MAX(id)').first + yield batch.pick('MIN(id), MAX(id)') end end end diff --git a/lib/gitlab/database/gitlab_schemas.yml b/lib/gitlab/database/gitlab_schemas.yml index 4a467d18f0a..d05eee7d6e6 100644 --- a/lib/gitlab/database/gitlab_schemas.yml +++ b/lib/gitlab/database/gitlab_schemas.yml @@ -300,6 +300,7 @@ licenses: :gitlab_main lists: :gitlab_main list_user_preferences: :gitlab_main loose_foreign_keys_deleted_records: :gitlab_shared +member_roles: :gitlab_main member_tasks: :gitlab_main members: :gitlab_main merge_request_assignees: :gitlab_main @@ -323,6 +324,10 @@ metrics_dashboard_annotations: :gitlab_main metrics_users_starred_dashboards: :gitlab_main milestone_releases: :gitlab_main milestones: :gitlab_main +ml_candidates: :gitlab_main +ml_experiments: :gitlab_main +ml_candidate_metrics: :gitlab_main +ml_candidate_params: :gitlab_main namespace_admin_notes: :gitlab_main namespace_aggregation_schedules: :gitlab_main namespace_bans: :gitlab_main @@ -331,6 +336,7 @@ namespace_package_settings: :gitlab_main namespace_root_storage_statistics: :gitlab_main namespace_ci_cd_settings: :gitlab_main namespace_settings: :gitlab_main +namespace_details: :gitlab_main namespaces: :gitlab_main namespaces_sync_events: :gitlab_main namespace_statistics: :gitlab_main @@ -529,6 +535,7 @@ user_custom_attributes: :gitlab_main user_details: :gitlab_main user_follow_users: :gitlab_main user_group_callouts: :gitlab_main +user_project_callouts: :gitlab_main user_highest_roles: :gitlab_main user_interacted_projects: :gitlab_main user_permission_export_uploads: :gitlab_main diff --git a/lib/gitlab/database/lock_writes_manager.rb b/lib/gitlab/database/lock_writes_manager.rb new file mode 100644 index 00000000000..cd483d616bb --- /dev/null +++ b/lib/gitlab/database/lock_writes_manager.rb @@ -0,0 +1,80 @@ +# frozen_string_literal: true + +module Gitlab + module Database + class LockWritesManager + TRIGGER_FUNCTION_NAME = 'gitlab_schema_prevent_write' + + def initialize(table_name:, connection:, database_name:, logger: nil) + @table_name = table_name + @connection = connection + @database_name = database_name + @logger = logger + end + + def lock_writes + logger&.info "Database: '#{database_name}', Table: '#{table_name}': Lock Writes".color(:yellow) + sql = <<-SQL + DROP TRIGGER IF EXISTS #{write_trigger_name(table_name)} ON #{table_name}; + CREATE TRIGGER #{write_trigger_name(table_name)} + BEFORE INSERT OR UPDATE OR DELETE OR TRUNCATE + ON #{table_name} + FOR EACH STATEMENT EXECUTE FUNCTION #{TRIGGER_FUNCTION_NAME}(); + SQL + + with_retries(connection) do + connection.execute(sql) + end + end + + def unlock_writes + logger&.info "Database: '#{database_name}', Table: '#{table_name}': Allow Writes".color(:green) + sql = <<-SQL + DROP TRIGGER IF EXISTS #{write_trigger_name(table_name)} ON #{table_name} + SQL + + with_retries(connection) do + connection.execute(sql) + end + end + + private + + attr_reader :table_name, :connection, :database_name, :logger + + def with_retries(connection, &block) + with_statement_timeout_retries do + with_lock_retries(connection) do + yield + end + end + end + + def with_statement_timeout_retries(times = 5) + current_iteration = 1 + begin + yield + rescue ActiveRecord::QueryCanceled => err # rubocop:disable Database/RescueQueryCanceled + if current_iteration <= times + current_iteration += 1 + retry + else + raise err + end + end + end + + def with_lock_retries(connection, &block) + Gitlab::Database::WithLockRetries.new( + klass: "gitlab:db:lock_writes", + logger: logger || Gitlab::AppLogger, + connection: connection + ).run(&block) + end + + def write_trigger_name(table_name) + "gitlab_schema_write_trigger_for_#{table_name}" + end + end + end +end diff --git a/lib/gitlab/database/migration_helpers.rb b/lib/gitlab/database/migration_helpers.rb index 4bb1d71ce18..db39524f4f6 100644 --- a/lib/gitlab/database/migration_helpers.rb +++ b/lib/gitlab/database/migration_helpers.rb @@ -505,14 +505,14 @@ module Gitlab # case another unique integer column can be used. Example: :user_id # # rubocop: disable Metrics/AbcSize - def update_column_in_batches(table, column, value, batch_size: nil, batch_column_name: :id) + def update_column_in_batches(table_name, column, value, batch_size: nil, batch_column_name: :id, disable_lock_writes: false) if transaction_open? raise 'update_column_in_batches can not be run inside a transaction, ' \ 'you can disable transactions by calling disable_ddl_transaction! ' \ 'in the body of your migration class' end - table = Arel::Table.new(table) + table = Arel::Table.new(table_name) count_arel = table.project(Arel.star.count.as('count')) count_arel = yield table, count_arel if block_given? @@ -559,7 +559,10 @@ module Gitlab update_arel = yield table, update_arel if block_given? - execute(update_arel.to_sql) + transaction do + execute("SELECT set_config('lock_writes.#{table_name}', 'false', true)") if disable_lock_writes + execute(update_arel.to_sql) + end # There are no more rows left to update. break unless stop_row @@ -1666,7 +1669,9 @@ into similar problems in the future (e.g. when new tables are created). end Gitlab::Database::QueryAnalyzers::RestrictAllowedSchemas.with_suppressed do - update_column_in_batches(table, new, old_value, batch_column_name: batch_column_name) + Gitlab::Database::QueryAnalyzers::GitlabSchemasValidateConnection.with_suppressed do + update_column_in_batches(table, new, old_value, batch_column_name: batch_column_name, disable_lock_writes: true) + end end add_not_null_constraint(table, new) unless old_col.null diff --git a/lib/gitlab/database/migrations/background_migration_helpers.rb b/lib/gitlab/database/migrations/background_migration_helpers.rb index 9bffed43077..25e75a10bb3 100644 --- a/lib/gitlab/database/migrations/background_migration_helpers.rb +++ b/lib/gitlab/database/migrations/background_migration_helpers.rb @@ -76,7 +76,7 @@ module Gitlab max = relation.arel_table[primary_column_name].maximum min = relation.arel_table[primary_column_name].minimum - start_id, end_id = relation.pluck(min, max).first + start_id, end_id = relation.pick(min, max) # `SingleDatabaseWorker.bulk_perform_in` schedules all jobs for # the same time, which is not helpful in most cases where we wish to diff --git a/lib/gitlab/database/migrations/base_background_runner.rb b/lib/gitlab/database/migrations/base_background_runner.rb index 2772502140e..a9440cafd30 100644 --- a/lib/gitlab/database/migrations/base_background_runner.rb +++ b/lib/gitlab/database/migrations/base_background_runner.rb @@ -38,7 +38,7 @@ module Gitlab per_background_migration_result_dir = File.join(@result_dir, migration_name) instrumentation = Instrumentation.new(result_dir: per_background_migration_result_dir) - batch_names = (1..).each.lazy.map { |i| "batch_#{i}"} + batch_names = (1..).each.lazy.map { |i| "batch_#{i}" } jobs.shuffle.each do |j| break if run_until <= Time.current diff --git a/lib/gitlab/database/migrations/batched_background_migration_helpers.rb b/lib/gitlab/database/migrations/batched_background_migration_helpers.rb index 936b986ea07..363fd0598f9 100644 --- a/lib/gitlab/database/migrations/batched_background_migration_helpers.rb +++ b/lib/gitlab/database/migrations/batched_background_migration_helpers.rb @@ -24,7 +24,7 @@ module Gitlab # class must be present in the Gitlab::BackgroundMigration module, and the batch class (if specified) must be # present in the Gitlab::BackgroundMigration::BatchingStrategies module. # - # If migration with same job_class_name, table_name, column_name, and job_aruments already exists, this helper + # If migration with same job_class_name, table_name, column_name, and job_arguments already exists, this helper # will log an warning and not create a new one. # # job_class_name - The background migration job class as a string @@ -107,6 +107,11 @@ module Gitlab status_event: status_event ) + if migration.job_class.respond_to?(:job_arguments_count) && migration.job_class.job_arguments_count != job_arguments.count + raise "Wrong number of job arguments for #{migration.job_class_name} " \ + "(given #{job_arguments.count}, expected #{migration.job_class.job_arguments_count})" + end + # Below `BatchedMigration` attributes were introduced after the # initial `batched_background_migrations` table was created, so any # migrations that ran relying on initial table schema would not know diff --git a/lib/gitlab/database/partitioning/sliding_list_strategy.rb b/lib/gitlab/database/partitioning/sliding_list_strategy.rb index 5cf32d3272c..4b5349f0327 100644 --- a/lib/gitlab/database/partitioning/sliding_list_strategy.rb +++ b/lib/gitlab/database/partitioning/sliding_list_strategy.rb @@ -77,7 +77,6 @@ module Gitlab end def validate_and_fix - return unless Feature.enabled?(:fix_sliding_list_partitioning) return if no_partitions_exist? old_default_value = current_default_value diff --git a/lib/gitlab/database/partitioning_migration_helpers/backfill_partitioned_table.rb b/lib/gitlab/database/partitioning_migration_helpers/backfill_partitioned_table.rb index 9cab2c51b3f..dcf457b9d63 100644 --- a/lib/gitlab/database/partitioning_migration_helpers/backfill_partitioned_table.rb +++ b/lib/gitlab/database/partitioning_migration_helpers/backfill_partitioned_table.rb @@ -25,7 +25,7 @@ module Gitlab parent_batch_relation = relation_scoped_to_range(source_table, source_column, start_id, stop_id) parent_batch_relation.each_batch(of: SUB_BATCH_SIZE) do |sub_batch| - sub_start_id, sub_stop_id = sub_batch.pluck(Arel.sql("MIN(#{source_column}), MAX(#{source_column})")).first + sub_start_id, sub_stop_id = sub_batch.pick(Arel.sql("MIN(#{source_column}), MAX(#{source_column})")) bulk_copy.copy_between(sub_start_id, sub_stop_id) sleep(PAUSE_SECONDS) diff --git a/lib/gitlab/database/postgres_hll/buckets.rb b/lib/gitlab/database/postgres_hll/buckets.rb index 76818bbf340..cbc9544d905 100644 --- a/lib/gitlab/database/postgres_hll/buckets.rb +++ b/lib/gitlab/database/postgres_hll/buckets.rb @@ -38,7 +38,7 @@ module Gitlab # # @param other_buckets_hash hash with HyperLogLog structure representation def merge_hash!(other_buckets_hash) - buckets.merge!(other_buckets_hash) {|_key, old, new| new > old ? new : old } + buckets.merge!(other_buckets_hash) { |_key, old, new| new > old ? new : old } end # Serialize instance underlying HyperLogLog structure to JSON format, that can be stored in various persistence layers @@ -61,7 +61,7 @@ module Gitlab num_uniques = ( ((TOTAL_BUCKETS**2) * (0.7213 / (1 + 1.079 / TOTAL_BUCKETS))) / - (num_zero_buckets + buckets.values.sum { |bucket_hash| 2**(-1 * bucket_hash)} ) + (num_zero_buckets + buckets.values.sum { |bucket_hash| 2**(-1 * bucket_hash) } ) ).to_i if num_zero_buckets > 0 && num_uniques < 2.5 * TOTAL_BUCKETS diff --git a/lib/gitlab/database/reindexing.rb b/lib/gitlab/database/reindexing.rb index e13dd3b2058..b96dffc99ac 100644 --- a/lib/gitlab/database/reindexing.rb +++ b/lib/gitlab/database/reindexing.rb @@ -27,6 +27,7 @@ module Gitlab # Hack: Before we do actual reindexing work, create async indexes Gitlab::Database::AsyncIndexes.create_pending_indexes! if Feature.enabled?(:database_async_index_creation, type: :ops) + Gitlab::Database::AsyncIndexes.drop_pending_indexes! if Feature.enabled?(:database_async_index_destruction, type: :ops) automatic_reindexing end diff --git a/lib/gitlab/database/reindexing/reindex_concurrently.rb b/lib/gitlab/database/reindexing/reindex_concurrently.rb index 152935bd734..60fa4deda39 100644 --- a/lib/gitlab/database/reindexing/reindex_concurrently.rb +++ b/lib/gitlab/database/reindexing/reindex_concurrently.rb @@ -20,7 +20,7 @@ module Gitlab def perform raise ReindexError, 'indexes serving an exclusion constraint are currently not supported' if index.exclusion? - raise ReindexError, 'index is a left-over temporary index from a previous reindexing run' if index.name =~ /#{TEMPORARY_INDEX_PATTERN}/ + raise ReindexError, 'index is a left-over temporary index from a previous reindexing run' if index.name =~ /#{TEMPORARY_INDEX_PATTERN}/o # Expression indexes require additional statistics in `pg_statistic`: # select * from pg_statistic where starelid = (select oid from pg_class where relname = 'some_index'); @@ -81,10 +81,10 @@ module Gitlab # Example lingering index name: some_index_ccnew1 # Example prefix: 'some_index' - prefix = lingering_index.name.gsub(/#{TEMPORARY_INDEX_PATTERN}/, '') + prefix = lingering_index.name.gsub(/#{TEMPORARY_INDEX_PATTERN}/o, '') # Example suffix: '_ccnew1' - suffix = lingering_index.name.match(/#{TEMPORARY_INDEX_PATTERN}/)[0] + suffix = lingering_index.name.match(/#{TEMPORARY_INDEX_PATTERN}/o)[0] # Only remove if the lingering index name could have been chosen # as a result of a REINDEX operation (considering that PostgreSQL diff --git a/lib/gitlab/database/with_lock_retries.rb b/lib/gitlab/database/with_lock_retries.rb index f2c5bb9088f..3206c5626c3 100644 --- a/lib/gitlab/database/with_lock_retries.rb +++ b/lib/gitlab/database/with_lock_retries.rb @@ -83,7 +83,7 @@ module Gitlab # @param [Boolean] raise_on_exhaustion whether to raise `AttemptsExhaustedError` when exhausting max attempts # @param [Proc] block of code that will be executed def run(raise_on_exhaustion: false, &block) - raise 'no block given' unless block_given? + raise 'no block given' unless block @block = block |