Skip to content

Commit c0e67e6

Browse files
authored
Merge pull request rails#49802 from composerinteralia/postgres-unrecoverable-connection-error
Recover from failed connections in PostgreSQL
2 parents 995092e + 73edae7 commit c0e67e6

File tree

2 files changed

+29
-17
lines changed

2 files changed

+29
-17
lines changed

activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -903,10 +903,10 @@ def exec_cache(sql, name, binds, async:, allow_retry:, materialize_transactions:
903903

904904
update_typemap_for_default_timezone
905905

906-
stmt_key = prepare_statement(sql, binds)
907-
type_casted_binds = type_casted_binds(binds)
908-
909906
with_raw_connection do |conn|
907+
stmt_key = prepare_statement(sql, binds, conn)
908+
type_casted_binds = type_casted_binds(binds)
909+
910910
log(sql, name, binds, type_casted_binds, stmt_key, async: async) do
911911
conn.exec_prepared(stmt_key, type_casted_binds)
912912
end
@@ -956,22 +956,20 @@ def sql_key(sql)
956956

957957
# Prepare the statement if it hasn't been prepared, return
958958
# the statement key.
959-
def prepare_statement(sql, binds)
960-
with_raw_connection(allow_retry: true, materialize_transactions: false) do |conn|
961-
sql_key = sql_key(sql)
962-
unless @statements.key? sql_key
963-
nextkey = @statements.next_key
964-
begin
965-
conn.prepare nextkey, sql
966-
rescue => e
967-
raise translate_exception_class(e, sql, binds)
968-
end
969-
# Clear the queue
970-
conn.get_last_result
971-
@statements[sql_key] = nextkey
959+
def prepare_statement(sql, binds, conn)
960+
sql_key = sql_key(sql)
961+
unless @statements.key? sql_key
962+
nextkey = @statements.next_key
963+
begin
964+
conn.prepare nextkey, sql
965+
rescue => e
966+
raise translate_exception_class(e, sql, binds)
972967
end
973-
@statements[sql_key]
968+
# Clear the queue
969+
conn.get_last_result
970+
@statements[sql_key] = nextkey
974971
end
972+
@statements[sql_key]
975973
end
976974

977975
# Connects to a PostgreSQL server and sets up the adapter depending on the

activerecord/test/cases/adapter_test.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,20 @@ def teardown
612612
assert_predicate @connection, :active?
613613
end
614614

615+
test "querying after a failed query restores and succeeds" do
616+
Post.first # Connection verified (and prepared statement pool populated if enabled)
617+
618+
remote_disconnect @connection
619+
620+
assert_raises(ActiveRecord::ConnectionFailed) do
621+
Post.first # Connection no longer verified after failed query
622+
end
623+
624+
assert Post.first # Verifying the connection causes a reconnect and the query succeeds
625+
626+
assert_predicate @connection, :active?
627+
end
628+
615629
test "transaction restores after remote disconnection" do
616630
remote_disconnect @connection
617631
Post.transaction do

0 commit comments

Comments
 (0)