From 0e9267767f19065fa513038253179ad6b05c29ab Mon Sep 17 00:00:00 2001 From: Matthew Draper Date: Wed, 8 Jun 2022 21:59:36 +0930 Subject: [PATCH] Ensure a lost connection upon COMMIT fails "cleanly" There's no point attempting to rollback in this case; we can instead just invalidate the now-lost transaction. Similarly, even though we can't immediately reconnect for a connection failure mid-transaction, we can and should drop and prior verification of the connection: the next out-of-transaction query attempt needs to fix it, not assume it's working. --- .../connection_adapters/abstract/transaction.rb | 3 +++ .../active_record/connection_adapters/abstract_adapter.rb | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb index f49abccdc4..f7624a0fce 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb @@ -495,6 +495,9 @@ def within_new_transaction(isolation: nil, joinable: true) begin commit_transaction + rescue ActiveRecord::ConnectionFailed + transaction.state.invalidate! unless transaction.state.completed? + raise rescue Exception rollback_transaction(transaction) unless transaction.state.completed? raise diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb index a7c6d19006..569c6fe928 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb @@ -941,6 +941,12 @@ def with_raw_connection(allow_retry: false, uses_transaction: true) end end + if retryable_connection_error?(translated_exception) + # There's a problem with the connection, but we couldn't attempt to + # reconnect. The connection is going to stay broken, so un-verify it. + @verified = false + end + raise translated_exception ensure dirty_current_transaction if uses_transaction