aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
authorRafael França <rafaelmfranca@gmail.com>2018-02-27 07:21:47 -0500
committerGitHub <noreply@github.com>2018-02-27 07:21:47 -0500
commit4464a391a0704d7434e751aa38f0c684349c42d9 (patch)
treeb24e7ea853ed82295df444de9419d152cc94fd53 /activerecord
parent5bf55685a3317f2716687a8fe471021a1bc042f0 (diff)
parent0bd7f4ad44c53832ec029a53a88461e9f6eab6f1 (diff)
downloadrails-4464a391a0704d7434e751aa38f0c684349c42d9.tar.gz
rails-4464a391a0704d7434e751aa38f0c684349c42d9.tar.bz2
rails-4464a391a0704d7434e751aa38f0c684349c42d9.zip
Merge pull request #31189 from tgxworld/raise_error_when_advisory_lock_is_not_releases
Raise an error if advisory lock in migrator was not released.
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/lib/active_record/migration.rb10
-rw-r--r--activerecord/test/cases/migration_test.rb19
2 files changed, 27 insertions, 2 deletions
diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb
index 5322571820..663b3c590a 100644
--- a/activerecord/lib/active_record/migration.rb
+++ b/activerecord/lib/active_record/migration.rb
@@ -140,6 +140,7 @@ module ActiveRecord
class ConcurrentMigrationError < MigrationError #:nodoc:
DEFAULT_MESSAGE = "Cannot run migrations because another migration process is currently running.".freeze
+ RELEASE_LOCK_FAILED_MESSAGE = "Failed to release advisory lock".freeze
def initialize(message = DEFAULT_MESSAGE)
super
@@ -1355,12 +1356,17 @@ module ActiveRecord
def with_advisory_lock
lock_id = generate_migrator_advisory_lock_id
- got_lock = Base.connection.get_advisory_lock(lock_id)
+ connection = Base.connection
+ got_lock = connection.get_advisory_lock(lock_id)
raise ConcurrentMigrationError unless got_lock
load_migrated # reload schema_migrations to be sure it wasn't changed by another process before we got the lock
yield
ensure
- Base.connection.release_advisory_lock(lock_id) if got_lock
+ if got_lock && !connection.release_advisory_lock(lock_id)
+ raise ConcurrentMigrationError.new(
+ ConcurrentMigrationError::RELEASE_LOCK_FAILED_MESSAGE
+ )
+ end
end
MIGRATOR_SALT = 2053462845
diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb
index a4b8664a85..c241ddc807 100644
--- a/activerecord/test/cases/migration_test.rb
+++ b/activerecord/test/cases/migration_test.rb
@@ -693,6 +693,25 @@ class MigrationTest < ActiveRecord::TestCase
assert_no_column Person, :last_name,
"without an advisory lock, the Migrator should not make any changes, but it did."
end
+
+ def test_with_advisory_lock_raises_the_right_error_when_it_fails_to_release_lock
+ migration = Class.new(ActiveRecord::Migration::Current).new
+ migrator = ActiveRecord::Migrator.new(:up, [migration], 100)
+ lock_id = migrator.send(:generate_migrator_advisory_lock_id)
+
+ e = assert_raises(ActiveRecord::ConcurrentMigrationError) do
+ silence_stream($stderr) do
+ migrator.send(:with_advisory_lock) do
+ ActiveRecord::Base.connection.release_advisory_lock(lock_id)
+ end
+ end
+ end
+
+ assert_match(
+ /#{ActiveRecord::ConcurrentMigrationError::RELEASE_LOCK_FAILED_MESSAGE}/,
+ e.message
+ )
+ end
end
private