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:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-06-20 13:43:29 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-06-20 13:43:29 +0300
commit3b1af5cc7ed2666ff18b718ce5d30fa5a2756674 (patch)
tree3bc4a40e0ee51ec27eabf917c537033c0c5b14d4 /lib/gitlab/database/query_analyzers/prevent_cross_database_modification.rb
parent9bba14be3f2c211bf79e15769cd9b77bc73a13bc (diff)
Add latest changes from gitlab-org/gitlab@16-1-stable-eev16.1.0-rc42
Diffstat (limited to 'lib/gitlab/database/query_analyzers/prevent_cross_database_modification.rb')
-rw-r--r--lib/gitlab/database/query_analyzers/prevent_cross_database_modification.rb50
1 files changed, 36 insertions, 14 deletions
diff --git a/lib/gitlab/database/query_analyzers/prevent_cross_database_modification.rb b/lib/gitlab/database/query_analyzers/prevent_cross_database_modification.rb
index d15a0eaa44c..b5a45eed3a4 100644
--- a/lib/gitlab/database/query_analyzers/prevent_cross_database_modification.rb
+++ b/lib/gitlab/database/query_analyzers/prevent_cross_database_modification.rb
@@ -5,6 +5,7 @@ module Gitlab
module QueryAnalyzers
class PreventCrossDatabaseModification < Database::QueryAnalyzers::Base
CrossDatabaseModificationAcrossUnsupportedTablesError = Class.new(QueryAnalyzerError)
+ QUERY_LIMIT = 10
# This method will allow cross database modifications within the block
# Example:
@@ -42,7 +43,8 @@ module Gitlab
context.merge!({
transaction_depth_by_db: Hash.new { |h, k| h[k] = 0 },
modified_tables_by_db: Hash.new { |h, k| h[k] = Set.new },
- ignored_tables: []
+ ignored_tables: [],
+ queries: []
})
end
@@ -71,6 +73,7 @@ module Gitlab
context[:transaction_depth_by_db][database] -= 1
if context[:transaction_depth_by_db][database] == 0
context[:modified_tables_by_db][database].clear
+ clear_queries
# Attempt to troubleshoot https://gitlab.com/gitlab-org/gitlab/-/issues/351531
::CrossDatabaseModification::TransactionStackTrackRecord.log_gitlab_transactions_stack(action: :end_of_transaction)
@@ -104,22 +107,25 @@ module Gitlab
# databases
return if tables == ['schema_migrations']
+ add_to_queries(sql)
context[:modified_tables_by_db][database].merge(tables)
all_tables = context[:modified_tables_by_db].values.flat_map(&:to_a)
schemas = ::Gitlab::Database::GitlabSchema.table_schemas!(all_tables)
-
schemas += ApplicationRecord.gitlab_transactions_stack
- if schemas.many?
- message = "Cross-database data modification of '#{schemas.to_a.join(", ")}' were detected within " \
- "a transaction modifying the '#{all_tables.to_a.join(", ")}' tables. " \
- "Please refer to https://docs.gitlab.com/ee/development/database/multiple_databases.html#removing-cross-database-transactions for details on how to resolve this exception."
+ unless ::Gitlab::Database::GitlabSchema.cross_transactions_allowed?(schemas)
+ messages = []
+ messages << "Cross-database data modification of '#{schemas.to_a.join(", ")}' were detected within " \
+ "a transaction modifying the '#{all_tables.to_a.join(", ")}' tables. "
+ messages << "Please refer to https://docs.gitlab.com/ee/development/database/multiple_databases.html#removing-cross-database-transactions " \
+ "for details on how to resolve this exception."
+ messages += cleaned_queries
- raise CrossDatabaseModificationAcrossUnsupportedTablesError, message
+ raise CrossDatabaseModificationAcrossUnsupportedTablesError, messages.join("\n\n")
end
rescue CrossDatabaseModificationAcrossUnsupportedTablesError => e
::Gitlab::ErrorTracking.track_exception(e, { gitlab_schemas: schemas, tables: all_tables, query: parsed.sql })
- raise if raise_exception?
+ raise if dev_or_test_env?
end
# rubocop:enable Metrics/AbcSize
@@ -159,12 +165,28 @@ module Gitlab
end
end
- # We only raise in tests for now otherwise some features will be broken
- # in development. For now we've mostly only added allowlist based on
- # spec names. Until we have allowed all the violations inline we don't
- # want to raise in development.
- def self.raise_exception?
- Rails.env.test?
+ def self.dev_or_test_env?
+ Gitlab.dev_or_test_env?
+ end
+
+ def self.clear_queries
+ return unless dev_or_test_env?
+
+ context[:queries].clear
+ end
+
+ def self.add_to_queries(sql)
+ return unless dev_or_test_env?
+
+ context[:queries].push(sql)
+ end
+
+ def self.cleaned_queries
+ return [] unless dev_or_test_env?
+
+ context[:queries].last(QUERY_LIMIT).each_with_index.map do |sql, i|
+ "#{i}: #{sql}"
+ end
end
def self.in_transaction?