Cleaned up database reconnection logic
authorAaron Schulz <aschulz@wikimedia.org>
Tue, 13 May 2014 21:34:23 +0000 (14:34 -0700)
committerAaron Schulz <aschulz@wikimedia.org>
Tue, 13 May 2014 21:34:23 +0000 (14:34 -0700)
* If callbacks are pending, just throw the normal query error
  exception for the failed query and clear the callbacks. This
  way an error is still reported, but the handle can be reused
  if desired, instead of being left broken. Also the reported
  error makes more sense.

bug: 65263
Change-Id: Icb2d372e65e6c62b5d5b90a442ea7b7a7f853adc

includes/db/Database.php

index f7fe980..dd89c44 100644 (file)
@@ -1104,20 +1104,25 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
                        # Transaction is gone, like it or not
                        $hadTrx = $this->mTrxLevel; // possible lost transaction
                        $this->mTrxLevel = 0;
+                       $this->mTrxIdleCallbacks = array(); // bug 65263
+                       $this->mTrxPreCommitCallbacks = array(); // bug 65263
                        wfDebug( "Connection lost, reconnecting...\n" );
 
                        if ( $this->ping() ) {
+                               global $wgRequestTime;
                                wfDebug( "Reconnected\n" );
                                $sqlx = substr( $commentedSql, 0, 500 );
                                $sqlx = strtr( $sqlx, "\t\n", '  ' );
-                               global $wgRequestTime;
                                $elapsed = round( microtime( true ) - $wgRequestTime, 3 );
                                if ( $elapsed < 300 ) {
                                        # Not a database error to lose a transaction after a minute or two
                                        wfLogDBError( "Connection lost and reconnected after {$elapsed}s, query: $sqlx" );
                                }
-                               if ( !$hadTrx ) {
-                                       # Should be safe to silently retry
+                               if ( $hadTrx ) {
+                                       # Leave $ret as false and let an error be reported.
+                                       # Callers may catch the exception and continue to use the DB.
+                               } else {
+                                       # Should be safe to silently retry (no trx and thus no callbacks)
                                        $ret = $this->doQuery( $commentedSql );
                                }
                        } else {