Skip to content

Commit 0dc356e

Browse files
committed
Merge pull request rails#6654 from stevecj/postgresql-auto-reconnect-2
Postgresql auto reconnect 2
2 parents b5c2384 + 4b1bca0 commit 0dc356e

File tree

3 files changed

+76
-1
lines changed

3 files changed

+76
-1
lines changed

activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,7 @@ def active?
474474
def reconnect!
475475
clear_cache!
476476
@connection.reset
477+
@open_transactions = 0
477478
configure_connection
478479
end
479480

@@ -1381,7 +1382,7 @@ def postgresql_version
13811382
UNIQUE_VIOLATION = "23505"
13821383

13831384
def translate_exception(exception, message)
1384-
case exception.result.error_field(PGresult::PG_DIAG_SQLSTATE)
1385+
case exception.result.try(:error_field, PGresult::PG_DIAG_SQLSTATE)
13851386
when UNIQUE_VIOLATION
13861387
RecordNotUnique.new(message, exception)
13871388
when FOREIGN_KEY_VIOLATION

activerecord/test/cases/adapters/postgresql/connection_test.rb

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,5 +81,77 @@ def test_schema_names_logs_name
8181
assert_equal 'SCHEMA', @connection.logged[0][1]
8282
end
8383

84+
def test_reconnection_after_simulated_disconnection_with_verify
85+
assert @connection.active?
86+
original_connection_pid = @connection.query('select pg_backend_pid()')
87+
88+
# Fail with bad connection after next query attempt.
89+
connection_class = class << @connection ; self ; end
90+
connection_class.class_eval <<-CODE
91+
def query_fake(*args)
92+
if @called ||= false
93+
@connection.stubs(:status).returns(PCconn::CONNECTION_BAD)
94+
raise PGError
95+
else
96+
@called = true
97+
@connection.unstub(:status)
98+
query_unfake(*args)
99+
end
100+
end
101+
102+
alias query_unfake query
103+
alias query query_fake
104+
CODE
105+
106+
begin
107+
@connection.verify!
108+
new_connection_pid = @connection.query('select pg_backend_pid()')
109+
ensure
110+
connection_class.class_eval <<-CODE
111+
alias query query_unfake
112+
undef query_fake
113+
CODE
114+
end
115+
116+
assert_equal original_connection_pid, new_connection_pid, "Should have a new underlying connection pid"
117+
end
118+
119+
# Must have with_manual_interventions set to true for this
120+
# test to run.
121+
# When prompted, restart the PostgreSQL server with the
122+
# "-m fast" option or kill the individual connection assuming
123+
# you know the incantation to do that.
124+
# To restart PostgreSQL 9.1 on OS X, installed via MacPorts, ...
125+
# sudo su postgres -c "pg_ctl restart -D /opt/local/var/db/postgresql91/defaultdb/ -m fast"
126+
def test_reconnection_after_actual_disconnection_with_verify
127+
skip "with_manual_interventions is false in configuration" unless ARTest.config['with_manual_interventions']
128+
129+
original_connection_pid = @connection.query('select pg_backend_pid()')
130+
131+
# Sanity check.
132+
assert @connection.active?
133+
134+
puts 'Kill the connection now (e.g. by restarting the PostgreSQL ' +
135+
'server with the "-m fast" option) and then press enter.'
136+
$stdin.gets
137+
138+
@connection.verify!
139+
140+
assert @connection.active?
141+
142+
# If we get no exception here, then either we re-connected successfully, or
143+
# we never actually got disconnected.
144+
new_connection_pid = @connection.query('select pg_backend_pid()')
145+
146+
assert_not_equal original_connection_pid, new_connection_pid,
147+
"umm -- looks like you didn't break the connection, because we're still " +
148+
"successfully querying with the same connection pid."
149+
150+
# Repair all fixture connections so other tests won't break.
151+
@fixture_connections.each do |c|
152+
c.verify!
153+
end
154+
end
155+
84156
end
85157
end

activerecord/test/config.example.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
default_connection: <%= defined?(JRUBY_VERSION) ? 'jdbcsqlite3' : 'sqlite3' %>
22

3+
with_manual_interventions: false
4+
35
connections:
46
jdbcderby:
57
arunit: activerecord_unittest

0 commit comments

Comments
 (0)