91 lines
2.5 KiB
Ruby
91 lines
2.5 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module Gitlab
|
|
module Database
|
|
module AsyncConstraints
|
|
module Validators
|
|
class Base
|
|
include AsyncDdlExclusiveLeaseGuard
|
|
extend ::Gitlab::Utils::Override
|
|
|
|
TIMEOUT_PER_ACTION = 1.day
|
|
STATEMENT_TIMEOUT = 12.hours
|
|
|
|
def initialize(record)
|
|
@record = record
|
|
end
|
|
|
|
def perform
|
|
try_obtain_lease do
|
|
if constraint_exists?
|
|
log_info('Starting to validate constraint')
|
|
validate_constraint_with_error_handling
|
|
log_info('Finished validating constraint')
|
|
else
|
|
log_info(skip_log_message)
|
|
record.destroy!
|
|
end
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
attr_reader :record
|
|
|
|
delegate :connection, :name, :table_name, :connection_db_config, to: :record
|
|
|
|
def constraint_exists?; end
|
|
|
|
def validate_constraint_with_error_handling
|
|
validate_constraint
|
|
record.destroy!
|
|
rescue StandardError => error
|
|
record.handle_exception!(error)
|
|
|
|
Gitlab::ErrorTracking.track_and_raise_for_dev_exception(error)
|
|
Gitlab::AppLogger.error(message: error.message, **logging_options)
|
|
end
|
|
|
|
def validate_constraint
|
|
set_statement_timeout do
|
|
connection.execute(<<~SQL.squish)
|
|
ALTER TABLE #{connection.quote_table_name(table_name)}
|
|
VALIDATE CONSTRAINT #{connection.quote_column_name(name)};
|
|
SQL
|
|
end
|
|
end
|
|
|
|
def set_statement_timeout
|
|
connection.execute(format("SET statement_timeout TO '%ds'", STATEMENT_TIMEOUT))
|
|
yield
|
|
ensure
|
|
connection.execute('RESET statement_timeout')
|
|
end
|
|
|
|
def lease_timeout
|
|
TIMEOUT_PER_ACTION
|
|
end
|
|
|
|
def log_info(message)
|
|
Gitlab::AppLogger.info(message: message, **logging_options)
|
|
end
|
|
|
|
def skip_log_message
|
|
"Skipping #{name} validation since it does not exist. " \
|
|
"The queuing entry will be deleted"
|
|
end
|
|
|
|
def logging_options
|
|
{
|
|
class: self.class.name.to_s,
|
|
connection_name: database_config_name,
|
|
constraint_name: name,
|
|
constraint_type: record.constraint_type,
|
|
table_name: table_name
|
|
}
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|