Make DeferredUpdates detect LBFactory transaction rounds
authorAaron Schulz <aschulz@wikimedia.org>
Fri, 9 Jun 2017 02:56:02 +0000 (19:56 -0700)
committerKrinkle <krinklemail@gmail.com>
Sat, 10 Jun 2017 15:22:32 +0000 (15:22 +0000)
Previously, tryOpportunisticExecute() tried to nest transaction rounds,
which would fail. Added LBFactory::hasTransactionRound() as needed.

Also cleaned up some unqualified class names in callbacks and set the
PRESEND flag for the JobQueueDB AutoCommitUpdate callback. Use the
proper getMasterDB() method while at it. These follow up 24842cfac.

Bug: T154425
Change-Id: Ib1d38f68bd217903d1a7d46fb15b7d7d9620daa6

includes/MediaWiki.php
includes/deferred/DeferredUpdates.php
includes/jobqueue/JobQueueDB.php
includes/jobqueue/JobRunner.php
includes/libs/rdbms/lbfactory/ILBFactory.php
includes/libs/rdbms/lbfactory/LBFactory.php

index 2125c23..364ed86 100644 (file)
@@ -898,9 +898,8 @@ class MediaWiki {
                        __METHOD__
                );
 
-               // Push lazilly-pushed jobs
                // Important: this must be the last deferred update added (T100085, T154425)
-               DeferredUpdates::addCallableUpdate( [ 'JobQueueGroup', 'pushLazyJobs' ] );
+               DeferredUpdates::addCallableUpdate( [ JobQueueGroup::class, 'pushLazyJobs' ] );
 
                // Do any deferred jobs
                DeferredUpdates::doUpdates( 'enqueue' );
index 51f5a28..a3a37f6 100644 (file)
@@ -286,7 +286,7 @@ class DeferredUpdates {
                }
 
                // Avoiding running updates without them having outer scope
-               if ( !self::getBusyDbConnections() ) {
+               if ( !self::areDatabaseTransactionsActive() ) {
                        self::doUpdates( $mode );
                        return true;
                }
@@ -356,16 +356,19 @@ class DeferredUpdates {
        }
 
        /**
-        * @return IDatabase[] Connection where commit() cannot be called yet
+        * @return bool If a transaction round is active or connection is not ready for commit()
         */
-       private static function getBusyDbConnections() {
-               $connsBusy = [];
-
+       private static function areDatabaseTransactionsActive() {
                $lbFactory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
+               if ( $lbFactory->hasTransactionRound() ) {
+                       return true;
+               }
+
+               $connsBusy = false;
                $lbFactory->forEachLB( function ( LoadBalancer $lb ) use ( &$connsBusy ) {
                        $lb->forEachOpenMasterConnection( function ( IDatabase $conn ) use ( &$connsBusy ) {
                                if ( $conn->writesOrCallbacksPending() || $conn->explicitTrxActive() ) {
-                                       $connsBusy[] = $conn;
+                                       $connsBusy = true;
                                }
                        } );
                } );
index 5e45730..9b9928d 100644 (file)
@@ -185,13 +185,16 @@ class JobQueueDB extends JobQueue {
         * @return void
         */
        protected function doBatchPush( array $jobs, $flags ) {
-               DeferredUpdates::addUpdate( new AutoCommitUpdate(
-                       wfGetDB( DB_MASTER ),
-                       __METHOD__,
-                       function ( IDatabase $dbw, $fname ) use ( $jobs, $flags ) {
-                               $this->doBatchPushInternal( $dbw, $jobs, $flags, $fname );
-                       }
-               ) );
+               DeferredUpdates::addUpdate(
+                       new AutoCommitUpdate(
+                               $this->getMasterDB(),
+                               __METHOD__,
+                               function ( IDatabase $dbw, $fname ) use ( $jobs, $flags ) {
+                                       $this->doBatchPushInternal( $dbw, $jobs, $flags, $fname );
+                               }
+                       ),
+                       DeferredUpdates::PRESEND
+               );
        }
 
        /**
index 0a0e9e0..ff90a9e 100644 (file)
@@ -289,9 +289,8 @@ class JobRunner implements LoggerAwareInterface {
                        $status = $job->run();
                        $error = $job->getLastError();
                        $this->commitMasterChanges( $lbFactory, $job, $fnameTrxOwner );
-                       // Push lazilly-pushed jobs
                        // Important: this must be the last deferred update added (T100085, T154425)
-                       DeferredUpdates::addCallableUpdate( [ 'JobQueueGroup', 'pushLazyJobs' ] );
+                       DeferredUpdates::addCallableUpdate( [ JobQueueGroup::class, 'pushLazyJobs' ] );
                        // Run any deferred update tasks; doUpdates() manages transactions itself
                        DeferredUpdates::doUpdates();
                } catch ( Exception $e ) {
index ac79acc..6e328f4 100644 (file)
@@ -192,6 +192,13 @@ interface ILBFactory {
         */
        public function rollbackMasterChanges( $fname = __METHOD__ );
 
+       /**
+        * Check if a transaction round is active
+        * @return bool
+        * @since 1.29
+        */
+       public function hasTransactionRound();
+
        /**
         * Determine if any master connection has pending changes
         * @return bool
index 53d5ef4..3567204 100644 (file)
@@ -250,6 +250,10 @@ abstract class LBFactory implements ILBFactory {
                } );
        }
 
+       public function hasTransactionRound() {
+               return ( $this->trxRoundId !== false );
+       }
+
        /**
         * Log query info if multi DB transactions are going to be committed now
         */