diff options
Diffstat (limited to 'lib/gitlab/database/async_indexes/index_base.rb')
-rw-r--r-- | lib/gitlab/database/async_indexes/index_base.rb | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/lib/gitlab/database/async_indexes/index_base.rb b/lib/gitlab/database/async_indexes/index_base.rb new file mode 100644 index 00000000000..bde75e12295 --- /dev/null +++ b/lib/gitlab/database/async_indexes/index_base.rb @@ -0,0 +1,90 @@ +# frozen_string_literal: true + +module Gitlab + module Database + module AsyncIndexes + class IndexBase + include AsyncDdlExclusiveLeaseGuard + extend ::Gitlab::Utils::Override + + TIMEOUT_PER_ACTION = 1.day + + def initialize(async_index) + @async_index = async_index + end + + def perform + try_obtain_lease do + if preconditions_met? + log_index_info("Starting async index #{action_type}") + execute_action_with_error_handling + log_index_info("Finished async index #{action_type}") + else + log_index_info(skip_log_message) + async_index.destroy! + end + end + end + + private + + attr_reader :async_index + + delegate :connection, :connection_db_config, to: :async_index + + def preconditions_met? + raise NotImplementedError, 'must implement preconditions_met?' + end + + def action_type + raise NotImplementedError, 'must implement action_type' + end + + def execute_action_with_error_handling + around_execution { execute_action } + rescue StandardError => error + async_index.handle_exception!(error) + + Gitlab::ErrorTracking.track_and_raise_for_dev_exception(error) + Gitlab::AppLogger.error(message: error.message, **logging_options) + end + + def around_execution + yield + end + + def execute_action + connection.execute(async_index.definition) + async_index.destroy! + end + + def index_exists? + connection.indexes(async_index.table_name).any? do |index| + index.name == async_index.name + end + end + + def lease_timeout + TIMEOUT_PER_ACTION + end + + def log_index_info(message) + Gitlab::AppLogger.info(message: message, **logging_options) + end + + def skip_log_message + "Skipping index #{action_type} since preconditions are not met. " \ + "The queuing entry will be deleted" + end + + def logging_options + { + table_name: async_index.table_name, + index_name: async_index.name, + class: self.class.name.to_s + } + end + end + end + end +end |