4533: Lock all tables before deleting contents.
authorTom Clegg <tom@curoverse.com>
Wed, 3 Dec 2014 20:40:18 +0000 (15:40 -0500)
committerTom Clegg <tom@curoverse.com>
Wed, 3 Dec 2014 20:40:18 +0000 (15:40 -0500)
services/api/app/controllers/database_controller.rb

index a2e15ed1561db247521eb8b65da36cadb08f9853..4c3f4d9f8e549160e681841338d253731812f363 100644 (file)
@@ -29,25 +29,33 @@ class DatabaseController < ApplicationController
     fixturesets = Dir.glob(Rails.root.join('test', 'fixtures', '*.yml')).
       collect { |yml| yml.match(/([^\/]*)\.yml$/)[1] }
 
-    # Delete existing fixtures (and everything else) from fixture
-    # tables
-    fixturesets.each do |x|
-      x.classify.constantize.unscoped.delete_all
+    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 SHARE ROW EXCLUSIVE MODE"
+
+      # Delete existing fixtures (and everything else) from fixture
+      # tables
+      fixturesets.each do |x|
+        x.classify.constantize.unscoped.delete_all
+      end
+
+      # 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)
+
+      # Dump cache of permissions etc.
+      Rails.cache.clear
+      ActiveRecord::Base.connection.clear_query_cache
+
+      # Reload database seeds
+      DatabaseSeeds.install
     end
 
-    # 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)
-
-    # Dump cache of permissions etc.
-    Rails.cache.clear
-    ActiveRecord::Base.connection.clear_query_cache
-
-    # Reload database seeds
-    DatabaseSeeds.install
-
     # Done.
     render json: {success: true}
   end