Permalink
Browse files

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
  • Loading branch information...
1 parent 44b6470 commit 680e4742bec472b649d1260b764fcd0e3ad115b7 @jeremy jeremy committed Nov 13, 2005
@@ -1,6 +1,6 @@
*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>]
@@ -22,6 +22,12 @@ class AbstractAdapter
include Quoting, DatabaseStatements, SchemaStatements
@@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:
@connection, @logger = connection, logger
@runtime = 0
@@ -40,9 +46,8 @@ def supports_migrations?
end
def reset_runtime #:nodoc:
- rt = @runtime
- @runtime = 0
- return rt
+ rt, @runtime = @runtime, 0
+ rt
end
protected
@@ -100,7 +105,14 @@ def format_log_entry(message, dump = nil)
def reconnect_if_inactive!
if respond_to?(:active?) and respond_to?(:reconnect!)
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
@logger.warn "#{adapter_name} does not yet support automatic reconnection." if @logger
end
@@ -136,6 +136,25 @@ def quoted_false
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 ======================================
def select_all(sql, name = nil) #:nodoc:
@@ -148,22 +167,10 @@ def select_one(sql, name = nil) #:nodoc:
end
def execute(sql, name = nil, retries = 2) #:nodoc:
- unless @logger
- @connection.query(sql)
- else
- log(sql, name) { @connection.query(sql) }
- end
+ log(sql, name) { @connection.query(sql) }
rescue ActiveRecord::StatementInvalid => exception
- if LOST_CONNECTION_ERROR_MESSAGES.any? { |msg| exception.message.split(":").first =~ /^#{msg}/ }
- @connection.real_connect(*@connection_options)
- 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."
+ if 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 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."
else
raise
end
@@ -127,6 +127,19 @@ def quote_column_name(name) #:nodoc:
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 ======================================
def execute(sql, name = nil) #:nodoc:

0 comments on commit 680e474

Please sign in to comment.