19217: Silence SQL logs during database reset.
[arvados.git] / services / api / app / controllers / database_controller.rb
index 831451435ef9f9adb47d974cdb91697f9db43f71..fa1e1ca43c64dc0b98a0587e703f0a075e890dae 100644 (file)
@@ -1,7 +1,13 @@
+# Copyright (C) The Arvados Authors. All rights reserved.
+#
+# SPDX-License-Identifier: AGPL-3.0
+
 class DatabaseController < ApplicationController
-  skip_before_filter :find_object_by_uuid
-  skip_before_filter :render_404_if_no_object
-  before_filter :admin_required
+  skip_before_action :find_object_by_uuid
+  skip_before_action :render_404_if_no_object
+  before_action :admin_required
+  around_action :silence_logs, only: [:reset]
+
   def reset
     raise ArvadosModel::PermissionDeniedError unless Rails.env == 'test'
 
@@ -10,8 +16,8 @@ class DatabaseController < ApplicationController
     # use @example.com email addresses when creating user records, so
     # we can tell they're not valuable.
     user_uuids = User.
-      where('email is null or email not like ?', '%@example.com').
-      collect &:uuid
+      where('email is null or (email not like ? and email not like ?)', '%@example.com', '%.example.com').
+      collect(&:uuid)
     fixture_uuids =
       YAML::load_file(File.expand_path('../../../test/fixtures/users.yml',
                                        __FILE__)).
@@ -29,34 +35,67 @@ class DatabaseController < ApplicationController
     fixturesets = Dir.glob(Rails.root.join('test', 'fixtures', '*.yml')).
       collect { |yml| yml.match(/([^\/]*)\.yml$/)[1] }
 
-    ActiveRecord::Base.transaction do
-      # Avoid deadlock by locking all tables before doing anything
-      # drastic.
-      table_names = '"' + fixturesets.sort.join('","') + '"'
-      ActiveRecord::Base.connection.execute \
-      "LOCK TABLE #{table_names} IN ACCESS EXCLUSIVE MODE"
-
-      # Delete existing fixtures (and everything else) from fixture
-      # tables
-      fixturesets.each do |x|
-        x.classify.constantize.unscoped.delete_all
-      end
+    # Don't reset keep_services: clients need to discover our
+    # integration-testing keepstores, not test fixtures.
+    fixturesets -= %w[keep_services]
+
+    table_names = '"' + ActiveRecord::Base.connection.tables.join('","') + '"'
 
-      # create_fixtures() is a no-op for cached fixture sets, so
-      # uncache them all.
-      ActiveRecord::Fixtures.reset_cache
-      ActiveRecord::Fixtures.
-        create_fixtures(Rails.root.join('test', 'fixtures'), fixturesets)
+    attempts_left = 20
+    begin
+      ActiveRecord::Base.transaction do
+        # Avoid deadlock by locking all tables before doing anything
+        # drastic.
+        ActiveRecord::Base.connection.execute \
+        "LOCK TABLE #{table_names} IN ACCESS EXCLUSIVE MODE"
 
-      # Dump cache of permissions etc.
-      Rails.cache.clear
-      ActiveRecord::Base.connection.clear_query_cache
+        # Delete existing fixtures (and everything else) from fixture
+        # tables
+        fixturesets.each do |x|
+          x.classify.constantize.unscoped.delete_all
+        end
 
-      # Reload database seeds
-      DatabaseSeeds.install
+        # create_fixtures() is a no-op for cached fixture sets, so
+        # uncache them all.
+        ActiveRecord::FixtureSet.reset_cache
+        ActiveRecord::FixtureSet.
+          create_fixtures(Rails.root.join('test', 'fixtures'), fixturesets)
+
+        # Dump cache of permissions etc.
+        Rails.cache.clear
+        ActiveRecord::Base.connection.clear_query_cache
+
+        # Reload database seeds
+        DatabaseSeeds.install
+      end
+    rescue ActiveRecord::StatementInvalid => e
+      if "#{e.inspect}" =~ /deadlock detected/i and (attempts_left -= 1) > 0
+        logger.info "Waiting for lock -- #{e.inspect}"
+        sleep 0.5
+        retry
+      end
+      raise
     end
 
+    require 'update_permissions'
+
+    refresh_permissions
+    refresh_trashed
+
     # Done.
-    render json: {success: true}
+    send_json success: true
+  end
+
+  protected
+
+  def silence_logs
+    Rails.logger.info("(logging level temporarily raised to :error, see #{__FILE__})")
+    orig = ActiveRecord::Base.logger.level
+    ActiveRecord::Base.logger.level = :error
+    begin
+      yield
+    ensure
+      ActiveRecord::Base.logger.level = orig
+    end
   end
 end