Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gitlab/database/migration_helpers/automatic_lock_writes_on_tables.rb')
-rw-r--r--lib/gitlab/database/migration_helpers/automatic_lock_writes_on_tables.rb75
1 files changed, 75 insertions, 0 deletions
diff --git a/lib/gitlab/database/migration_helpers/automatic_lock_writes_on_tables.rb b/lib/gitlab/database/migration_helpers/automatic_lock_writes_on_tables.rb
new file mode 100644
index 00000000000..0aa4b0d01c4
--- /dev/null
+++ b/lib/gitlab/database/migration_helpers/automatic_lock_writes_on_tables.rb
@@ -0,0 +1,75 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module MigrationHelpers
+ module AutomaticLockWritesOnTables
+ extend ActiveSupport::Concern
+
+ included do
+ class_attribute :skip_automatic_lock_on_writes
+ end
+
+ def exec_migration(connection, direction)
+ return super if %w[main ci].exclude?(Gitlab::Database.db_config_name(connection))
+ return super if automatic_lock_on_writes_disabled?
+
+ # This compares the tables only on the `public` schema. Partitions are not affected
+ tables = connection.tables
+ super
+ new_tables = connection.tables - tables
+
+ new_tables.each do |table_name|
+ lock_writes_on_table(connection, table_name) if should_lock_writes_on_table?(table_name)
+ end
+ end
+
+ private
+
+ def automatic_lock_on_writes_disabled?
+ # Feature flags are set on the main database, see tables features/feature_gates.
+ # That is why we switch the ActiveRecord::Base.connection temporarily here back to the 'main' database
+ # for the cases when the migration is targeting another database, like the 'ci' database.
+ with_restored_connection_stack do |_|
+ Gitlab::Database::QueryAnalyzers::RestrictAllowedSchemas.with_suppressed do
+ skip_automatic_lock_on_writes ||
+ Gitlab::Utils.to_boolean(ENV['SKIP_AUTOMATIC_LOCK_ON_WRITES']) ||
+ Feature.disabled?(:automatic_lock_writes_on_table, type: :ops)
+ end
+ end
+ end
+
+ def should_lock_writes_on_table?(table_name)
+ # currently gitlab_schema represents only present existing tables, this is workaround for deleted tables
+ # that should be skipped as they will be removed in a future migration.
+ return false if Gitlab::Database::GitlabSchema::DELETED_TABLES[table_name]
+
+ table_schema = Gitlab::Database::GitlabSchema.table_schema(table_name.to_s, undefined: false)
+
+ if table_schema.nil?
+ error_message = <<~ERROR
+ No gitlab_schema is defined for the table #{table_name}. Please consider
+ adding it to the database dictionary.
+ More info: https://docs.gitlab.com/ee/development/database/database_dictionary.html
+ ERROR
+ raise error_message
+ end
+
+ return false unless %i[gitlab_main gitlab_ci].include?(table_schema)
+
+ Gitlab::Database.gitlab_schemas_for_connection(connection).exclude?(table_schema)
+ end
+
+ def lock_writes_on_table(connection, table_name)
+ database_name = Gitlab::Database.db_config_name(connection)
+ LockWritesManager.new(
+ table_name: table_name,
+ connection: connection,
+ database_name: database_name,
+ logger: Logger.new($stdout)
+ ).lock_writes
+ end
+ end
+ end
+ end
+end