Skip to content

Commit

Permalink
Also handle ActiveRecord::DatabaseConnectionError
Browse files Browse the repository at this point in the history
  • Loading branch information
seven1m committed Aug 16, 2023
1 parent 1e6c738 commit 8545eb1
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 27 deletions.
2 changes: 2 additions & 0 deletions lib/activerecord/mysql/reconnect.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ module Activerecord::Mysql::Reconnect

HANDLE_ERROR = [
ActiveRecord::ConnectionNotEstablished,
ActiveRecord::DatabaseConnectionError,
ActiveRecord::StatementInvalid,
Mysql2::Error,
]
Expand All @@ -47,6 +48,7 @@ module Activerecord::Mysql::Reconnect
lost_connection: "Lost connection to MySQL server at 'reading initial communication packet'",
not_connected: "MySQL client is not connected",
killed: 'Connection was killed',
issue_connecting: 'There is an issue connecting with your hostname',
}

READ_SQL_REGEXP = /\A\s*(?:SELECT|SHOW|SET)\b/i
Expand Down
41 changes: 14 additions & 27 deletions spec/activerecord-mysql-reconnect_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -452,62 +452,49 @@
end

let(:mysql_error) do
Mysql2::Error.const_defined?(:ConnectionError) ? Mysql2::Error::ConnectionError : Mysql2::Error
Mysql2::Error::ConnectionError
end

before do
allow_any_instance_of(mysql_error).to receive(:message).and_return('Lost connection to MySQL server during query')
allow_any_instance_of(ActiveRecord::StatementInvalid).to receive(:message).and_return('Lost connection to MySQL server during query')
allow_any_instance_of(ActiveRecord::DatabaseConnectionError).to receive(:message).and_return('Lost connection to MySQL server during query')
end

context "when retry failed " do
specify do
if ActiveRecord::VERSION::MAJOR < 6
expect(ActiveRecord::Base.logger).to receive(:warn).with(warning_template % [
"MySQL server has gone away. Trying to reconnect in 0.5 seconds.",
"#{mysql_error}: Lost connection to MySQL server during query: SELECT `employees`.* FROM `employees` [ActiveRecord::StatementInvalid]",
])
else
expect(ActiveRecord::Base.logger).to receive(:warn).with(warning_template % [
"MySQL server has gone away. Trying to reconnect in 0.5 seconds.",
"#{mysql_error}: Lost connection to MySQL server during query [ActiveRecord::StatementInvalid]",
])
end

expect(ActiveRecord::Base.logger).to receive(:warn).with(warning_template % [
"MySQL server has gone away. Trying to reconnect in 0.5 seconds.",
"Lost connection to MySQL server during query [ActiveRecord::StatementInvalid]",
])

(1.0..4.5).step(0.5).each do |sec|
expect(ActiveRecord::Base.logger).to receive(:warn).with(warning_template % [
"MySQL server has gone away. Trying to reconnect in #{sec} seconds.",
"Lost connection to MySQL server during query [#{mysql_error}]",
"Lost connection to MySQL server during query [ActiveRecord::DatabaseConnectionError]",
])
end

expect(ActiveRecord::Base.logger).to receive(:warn).with(warning_template % [
"Query retry failed.",
"Lost connection to MySQL server during query [#{mysql_error}]",
"Lost connection to MySQL server during query [ActiveRecord::DatabaseConnectionError]",
])

expect(Employee.all.length).to eq 1000
MysqlServer.stop

expect {
Employee.all.length
}.to raise_error(mysql_error)
}.to raise_error(ActiveRecord::DatabaseConnectionError)
end
end

context "when retry succeeded" do
specify do
if ActiveRecord::VERSION::MAJOR < 6
expect(ActiveRecord::Base.logger).to receive(:warn).with(warning_template % [
"MySQL server has gone away. Trying to reconnect in 0.5 seconds.",
"#{mysql_error}: Lost connection to MySQL server during query: SELECT `employees`.* FROM `employees` [ActiveRecord::StatementInvalid]",
])
else
expect(ActiveRecord::Base.logger).to receive(:warn).with(warning_template % [
"MySQL server has gone away. Trying to reconnect in 0.5 seconds.",
"#{mysql_error}: Lost connection to MySQL server during query [ActiveRecord::StatementInvalid]",
])
end
expect(ActiveRecord::Base.logger).to receive(:warn).with(warning_template % [
"MySQL server has gone away. Trying to reconnect in 0.5 seconds.",
"Lost connection to MySQL server during query [ActiveRecord::StatementInvalid]",
])

expect(Employee.all.length).to eq 1000
MysqlServer.restart
Expand Down

0 comments on commit 8545eb1

Please sign in to comment.