Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Recover from failed connections in PostgreSQL #49802

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -907,10 +907,10 @@ def exec_cache(sql, name, binds, async:, allow_retry:, materialize_transactions:

update_typemap_for_default_timezone

stmt_key = prepare_statement(sql, binds)
type_casted_binds = type_casted_binds(binds)

with_raw_connection do |conn|
stmt_key = prepare_statement(sql, binds, conn)
type_casted_binds = type_casted_binds(binds)

log(sql, name, binds, type_casted_binds, stmt_key, async: async) do
conn.exec_prepared(stmt_key, type_casted_binds)
end
Expand Down Expand Up @@ -960,22 +960,20 @@ def sql_key(sql)

# Prepare the statement if it hasn't been prepared, return
# the statement key.
def prepare_statement(sql, binds)
with_raw_connection(allow_retry: true, materialize_transactions: false) do |conn|
sql_key = sql_key(sql)
unless @statements.key? sql_key
nextkey = @statements.next_key
begin
conn.prepare nextkey, sql
rescue => e
raise translate_exception_class(e, sql, binds)
end
# Clear the queue
conn.get_last_result
@statements[sql_key] = nextkey
def prepare_statement(sql, binds, conn)
sql_key = sql_key(sql)
unless @statements.key? sql_key
nextkey = @statements.next_key
begin
conn.prepare nextkey, sql
rescue => e
raise translate_exception_class(e, sql, binds)
end
@statements[sql_key]
# Clear the queue
conn.get_last_result
@statements[sql_key] = nextkey
end
@statements[sql_key]
end

# Connects to a PostgreSQL server and sets up the adapter depending on the
Expand Down
14 changes: 14 additions & 0 deletions activerecord/test/cases/adapter_test.rb
Expand Up @@ -612,6 +612,20 @@ def teardown
assert_predicate @connection, :active?
end

test "querying after a failed query restores and succeeds" do
Post.first # Connection verified (and prepared statement pool populated if enabled)

remote_disconnect @connection

assert_raises(ActiveRecord::ConnectionFailed) do
Post.first # Connection no longer verified after failed query
end

assert Post.first # Verifying the connection causes a reconnect and the query succeeds

assert_predicate @connection, :active?
end

test "transaction restores after remote disconnection" do
remote_disconnect @connection
Post.transaction do
Expand Down