1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

r3042@asus: jeremy | 2005-11-13 01:51:08 -0800

MySQL active? and reconnect!  References #428.
 r3043@asus:  jeremy | 2005-11-13 01:58:28 -0800
 SQLite active? and reconnect!  References #428.
 r3044@asus:  jeremy | 2005-11-13 02:02:27 -0800
 Update CHANGELOG with admonishment regarding avoidance of the log method.


git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@3001 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
This commit is contained in:
Jeremy Kemper 2005-11-13 10:03:03 +00:00
parent 44b64704dd
commit 680e4742be
4 changed files with 52 additions and 20 deletions

View file

@ -1,6 +1,6 @@
*SVN* *SVN*
* When AbstractAdapter#log rescues an exception, attempt to detect and reconnect to an inactive database connection. Connection adapter must respond to the active? and reconnect! instance methods. Initial support for PostgreSQL. [Jeremy Kemper] * When AbstractAdapter#log rescues an exception, attempt to detect and reconnect to an inactive database connection. Connection adapter must respond to the active? and reconnect! instance methods. Initial support for PostgreSQL, MySQL, and SQLite. Make certain that all statements which may need reconnection are performed within a logged block: for example, this means no avoiding log(sql, name) { } if @logger.nil? [Jeremy Kemper]
* Much faster Oracle column reflection. #2848 [Michael Schoen <schoenm@earthlink.net>] * Much faster Oracle column reflection. #2848 [Michael Schoen <schoenm@earthlink.net>]

View file

@ -22,6 +22,12 @@ module ActiveRecord
include Quoting, DatabaseStatements, SchemaStatements include Quoting, DatabaseStatements, SchemaStatements
@@row_even = true @@row_even = true
@@reconnect_success = 0
@@reconnect_failure = 0
def self.reconnect_success_rate
@@reconnect_success.to_f / (@@reconnect_success + @@reconnect_failure)
end
def initialize(connection, logger = nil) #:nodoc: def initialize(connection, logger = nil) #:nodoc:
@connection, @logger = connection, logger @connection, @logger = connection, logger
@runtime = 0 @runtime = 0
@ -40,9 +46,8 @@ module ActiveRecord
end end
def reset_runtime #:nodoc: def reset_runtime #:nodoc:
rt = @runtime rt, @runtime = @runtime, 0
@runtime = 0 rt
return rt
end end
protected protected
@ -100,7 +105,14 @@ module ActiveRecord
def reconnect_if_inactive! def reconnect_if_inactive!
if respond_to?(:active?) and respond_to?(:reconnect!) if respond_to?(:active?) and respond_to?(:reconnect!)
reconnect! unless active? reconnect! unless active?
raise ActiveRecord::ConnectionFailed unless active? if active?
@@reconnect_success += 1
@logger.info "#{adapter_name} automatically reconnected. Success rate: #{'%.2f' % self.class.reconnect_success_rate}%" if @logger
else
@@reconnect_failure += 1
@logger.warn "#{adapter_name} automatic reconnection failed. Success rate: #{'%.2f' % self.class.reconnect_success_rate}%" if @logger
raise ActiveRecord::ConnectionFailed
end
else else
@logger.warn "#{adapter_name} does not yet support automatic reconnection." if @logger @logger.warn "#{adapter_name} does not yet support automatic reconnection." if @logger
end end

View file

@ -136,6 +136,25 @@ module ActiveRecord
end end
# CONNECTION MANAGEMENT ====================================
def active?
@connection.stat if @connection.respond_to?(:stat)
true
rescue Mysql::Error
false
end
def reconnect!
if @connection.respond_to?(:ping)
@connection.ping
else
@connection.close rescue nil
@connection.real_connect(*@connection_options)
end
end
# DATABASE STATEMENTS ====================================== # DATABASE STATEMENTS ======================================
def select_all(sql, name = nil) #:nodoc: def select_all(sql, name = nil) #:nodoc:
@ -148,22 +167,10 @@ module ActiveRecord
end end
def execute(sql, name = nil, retries = 2) #:nodoc: def execute(sql, name = nil, retries = 2) #:nodoc:
unless @logger
@connection.query(sql)
else
log(sql, name) { @connection.query(sql) } log(sql, name) { @connection.query(sql) }
end
rescue ActiveRecord::StatementInvalid => exception rescue ActiveRecord::StatementInvalid => exception
if LOST_CONNECTION_ERROR_MESSAGES.any? { |msg| exception.message.split(":").first =~ /^#{msg}/ } if exception.message.split(":").first =~ /Packets out of order/
@connection.real_connect(*@connection_options) raise ActiveRecord::StatementInvalid, "'Packets out of order' error was received from the database. Please update your mysql bindings (gem install mysql) and read http://dev.mysql.com/doc/mysql/en/password-hashing.html for more information. If you're on Windows, use the Instant Rails installer to get the updated mysql bindings."
unless @logger
@connection.query(sql)
else
@logger.info "Retrying invalid statement with reopened connection"
log(sql, name) { @connection.query(sql) }
end
elsif exception.message.split(":").first =~ /Packets out of order/
raise ActiveRecord::StatementInvalid, "'Packets out of order' error was received from the database. Please update your mysql bindings (gem update mysql) and read http://dev.mysql.com/doc/mysql/en/password-hashing.html for more information."
else else
raise raise
end end

View file

@ -127,6 +127,19 @@ module ActiveRecord
end end
# CONNECTION MANAGEMENT ====================================
def active?
# TODO: SQLite is an embedded db, it doesn't lose connections,
# but perhaps some of its exceptions merit a retry, such as
# LockedException.
true
end
def reconnect!
end
# DATABASE STATEMENTS ====================================== # DATABASE STATEMENTS ======================================
def execute(sql, name = nil) #:nodoc: def execute(sql, name = nil) #:nodoc: