diff options
Diffstat (limited to 'spec/support/database/prevent_cross_database_modification.rb')
-rw-r--r-- | spec/support/database/prevent_cross_database_modification.rb | 24 |
1 files changed, 18 insertions, 6 deletions
diff --git a/spec/support/database/prevent_cross_database_modification.rb b/spec/support/database/prevent_cross_database_modification.rb index b4c968e3c41..7ded85b65ce 100644 --- a/spec/support/database/prevent_cross_database_modification.rb +++ b/spec/support/database/prevent_cross_database_modification.rb @@ -33,8 +33,10 @@ module Database end def cleanup_with_cross_database_modification_prevented - ActiveSupport::Notifications.unsubscribe(PreventCrossDatabaseModification.cross_database_context[:subscriber]) - PreventCrossDatabaseModification.cross_database_context[:enabled] = false + if PreventCrossDatabaseModification.cross_database_context + ActiveSupport::Notifications.unsubscribe(PreventCrossDatabaseModification.cross_database_context[:subscriber]) + PreventCrossDatabaseModification.cross_database_context[:enabled] = false + end end end @@ -55,8 +57,11 @@ module Database end def self.prevent_cross_database_modification!(connection, sql) + return unless cross_database_context return unless cross_database_context[:enabled] + return if connection.pool.instance_of?(ActiveRecord::ConnectionAdapters::NullPool) + database = connection.pool.db_config.name if sql.start_with?('SAVEPOINT') @@ -74,6 +79,8 @@ module Database return if cross_database_context[:transaction_depth_by_db].values.all?(&:zero?) + # PgQuery might fail in some cases due to limited nesting: + # https://github.com/pganalyze/pg_query/issues/209 parsed_query = PgQuery.parse(sql) tables = sql.downcase.include?(' for update') ? parsed_query.tables : parsed_query.dml_tables @@ -87,7 +94,8 @@ module Database if schemas.many? raise Database::PreventCrossDatabaseModification::CrossDatabaseModificationAcrossUnsupportedTablesError, "Cross-database data modification of '#{schemas.to_a.join(", ")}' were detected within " \ - "a transaction modifying the '#{all_tables.to_a.join(", ")}'" + "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." end end end @@ -96,16 +104,20 @@ end Gitlab::Database.singleton_class.prepend( Database::PreventCrossDatabaseModification::GitlabDatabaseMixin) +CROSS_DB_MODIFICATION_ALLOW_LIST = Set.new(YAML.load_file(File.join(__dir__, 'cross-database-modification-allowlist.yml'))).freeze + RSpec.configure do |config| config.include(::Database::PreventCrossDatabaseModification::SpecHelpers) # Using before and after blocks because the around block causes problems with the let_it_be # record creations. It makes an extra savepoint which breaks the transaction count logic. - config.before(:each, :prevent_cross_database_modification) do - with_cross_database_modification_prevented + config.before do |example_file| + if CROSS_DB_MODIFICATION_ALLOW_LIST.exclude?(example_file.file_path) + with_cross_database_modification_prevented + end end - config.after(:each, :prevent_cross_database_modification) do + config.after do |example_file| cleanup_with_cross_database_modification_prevented end end |