From: Aaron Schulz Date: Fri, 9 Jun 2017 02:56:02 +0000 (-0700) Subject: Make DeferredUpdates detect LBFactory transaction rounds X-Git-Tag: 1.31.0-rc.0~3020^2 X-Git-Url: http://git.cyclocoop.org/%7B%24www_url%7Dadmin/compta/categories/modifier.php?a=commitdiff_plain;h=95fdff36c251d9d1807c7b5b0bf84acc457f0d1e;p=lhc%2Fweb%2Fwiklou.git Make DeferredUpdates detect LBFactory transaction rounds 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 --- diff --git a/includes/MediaWiki.php b/includes/MediaWiki.php index 2125c23499..364ed86edf 100644 --- a/includes/MediaWiki.php +++ b/includes/MediaWiki.php @@ -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' ); diff --git a/includes/deferred/DeferredUpdates.php b/includes/deferred/DeferredUpdates.php index 51f5a28c3d..a3a37f6f2e 100644 --- a/includes/deferred/DeferredUpdates.php +++ b/includes/deferred/DeferredUpdates.php @@ -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; } } ); } ); diff --git a/includes/jobqueue/JobQueueDB.php b/includes/jobqueue/JobQueueDB.php index 5e457300e9..9b9928d1f3 100644 --- a/includes/jobqueue/JobQueueDB.php +++ b/includes/jobqueue/JobQueueDB.php @@ -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 + ); } /** diff --git a/includes/jobqueue/JobRunner.php b/includes/jobqueue/JobRunner.php index 0a0e9e0eb0..ff90a9ebf8 100644 --- a/includes/jobqueue/JobRunner.php +++ b/includes/jobqueue/JobRunner.php @@ -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 ) { diff --git a/includes/libs/rdbms/lbfactory/ILBFactory.php b/includes/libs/rdbms/lbfactory/ILBFactory.php index ac79acc64f..6e328f4b4c 100644 --- a/includes/libs/rdbms/lbfactory/ILBFactory.php +++ b/includes/libs/rdbms/lbfactory/ILBFactory.php @@ -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 diff --git a/includes/libs/rdbms/lbfactory/LBFactory.php b/includes/libs/rdbms/lbfactory/LBFactory.php index 53d5ef4f40..3567204a82 100644 --- a/includes/libs/rdbms/lbfactory/LBFactory.php +++ b/includes/libs/rdbms/lbfactory/LBFactory.php @@ -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 */