aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--activerecord/CHANGELOG.md4
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb3
-rw-r--r--activerecord/test/cases/adapters/mysql2/transaction_test.rb2
-rw-r--r--activerecord/test/cases/adapters/postgresql/transaction_test.rb29
4 files changed, 35 insertions, 3 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index e6a41ec281..34ef5c79e1 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -144,8 +144,8 @@
*Jeremy Green*
-* Add new error class `TransactionTimeout` for MySQL adapter which will be raised
- when lock wait time expires.
+* Add new error class `TransactionTimeout` which will be raised
+ when lock wait timeout exceeded.
*Gabriel Courtemanche*
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
index 2c3c1df2a9..46863c41ab 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
@@ -391,6 +391,7 @@ module ActiveRecord
UNIQUE_VIOLATION = "23505"
SERIALIZATION_FAILURE = "40001"
DEADLOCK_DETECTED = "40P01"
+ LOCK_NOT_AVAILABLE = "55P03"
def translate_exception(exception, message)
return exception unless exception.respond_to?(:result)
@@ -410,6 +411,8 @@ module ActiveRecord
SerializationFailure.new(message)
when DEADLOCK_DETECTED
Deadlocked.new(message)
+ when LOCK_NOT_AVAILABLE
+ TransactionTimeout.new(message)
else
super
end
diff --git a/activerecord/test/cases/adapters/mysql2/transaction_test.rb b/activerecord/test/cases/adapters/mysql2/transaction_test.rb
index 7b032fed6d..ac9a8d9dfb 100644
--- a/activerecord/test/cases/adapters/mysql2/transaction_test.rb
+++ b/activerecord/test/cases/adapters/mysql2/transaction_test.rb
@@ -60,7 +60,7 @@ module ActiveRecord
end
end
- test "raises TransactionTimeout when mysql raises ER_LOCK_WAIT_TIMEOUT" do
+ test "raises TransactionTimeout when lock wait timeout exceeded" do
assert_raises(ActiveRecord::TransactionTimeout) do
s = Sample.create!(value: 1)
latch1 = Concurrent::CountDownLatch.new
diff --git a/activerecord/test/cases/adapters/postgresql/transaction_test.rb b/activerecord/test/cases/adapters/postgresql/transaction_test.rb
index f56adf4a5e..b6aec8e993 100644
--- a/activerecord/test/cases/adapters/postgresql/transaction_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/transaction_test.rb
@@ -91,6 +91,35 @@ module ActiveRecord
end
end
+ test "raises TransactionTimeout when lock wait timeout exceeded" do
+ skip unless ActiveRecord::Base.connection.postgresql_version >= 90300
+ assert_raises(ActiveRecord::TransactionTimeout) do
+ s = Sample.create!(value: 1)
+ latch1 = Concurrent::CountDownLatch.new
+ latch2 = Concurrent::CountDownLatch.new
+
+ thread = Thread.new do
+ Sample.transaction do
+ Sample.lock.find(s.id)
+ latch1.count_down
+ latch2.wait
+ end
+ end
+
+ begin
+ Sample.transaction do
+ latch1.wait
+ Sample.connection.execute("SET lock_timeout = 1")
+ Sample.lock.find(s.id)
+ end
+ ensure
+ Sample.connection.execute("SET lock_timeout = DEFAULT")
+ latch2.count_down
+ thread.join
+ end
+ end
+ end
+
private
def with_warning_suppression