Catrope has uploaded a new change for review. https://gerrit.wikimedia.org/r/311607
Change subject: Revert "Move LBFactorySimple to /libs/rdbms" ...................................................................... Revert "Move LBFactorySimple to /libs/rdbms" Breaks login and setting preferences in MW-Vagrant with: InvalidArgumentException from line 90 of /vagrant/mediawiki/includes/libs/rdbms/lbfactory/LBFactorySimple.php: LBFactorySimple::newExternalLB: Unknown cluster "extension1" This reverts commit d175b391ae2a77e3183b2608bb4422782af092a1. Change-Id: I918422aeb8b62a443ae8dfd36c902394312fbdd1 --- M autoload.php M includes/ServiceWiring.php M includes/Setup.php M includes/db/loadbalancer/LBFactoryMW.php M includes/db/loadbalancer/LBFactoryMulti.php A includes/db/loadbalancer/LBFactorySimple.php M includes/libs/rdbms/lbfactory/LBFactory.php D includes/libs/rdbms/lbfactory/LBFactorySimple.php M tests/phpunit/includes/MediaWikiServicesTest.php M tests/phpunit/includes/db/LBFactoryTest.php 10 files changed, 286 insertions(+), 319 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/core refs/changes/07/311607/1 diff --git a/autoload.php b/autoload.php index 52c929a..035c152 100644 --- a/autoload.php +++ b/autoload.php @@ -660,7 +660,7 @@ 'LBFactory' => __DIR__ . '/includes/libs/rdbms/lbfactory/LBFactory.php', 'LBFactoryMW' => __DIR__ . '/includes/db/loadbalancer/LBFactoryMW.php', 'LBFactoryMulti' => __DIR__ . '/includes/db/loadbalancer/LBFactoryMulti.php', - 'LBFactorySimple' => __DIR__ . '/includes/libs/rdbms/lbfactory/LBFactorySimple.php', + 'LBFactorySimple' => __DIR__ . '/includes/db/loadbalancer/LBFactorySimple.php', 'LBFactorySingle' => __DIR__ . '/includes/db/loadbalancer/LBFactorySingle.php', 'LCStore' => __DIR__ . '/includes/cache/localisation/LCStore.php', 'LCStoreCDB' => __DIR__ . '/includes/cache/localisation/LCStoreCDB.php', diff --git a/includes/ServiceWiring.php b/includes/ServiceWiring.php index 7a34b3a..4ab412e 100644 --- a/includes/ServiceWiring.php +++ b/includes/ServiceWiring.php @@ -43,53 +43,15 @@ return [ 'DBLoadBalancerFactory' => function( MediaWikiServices $services ) { - $mainConfig = $services->getMainConfig(); + $config = $services->getMainConfig()->get( 'LBFactoryConf' ); - $lbConf = $mainConfig->get( 'LBFactoryConf' ); - $lbConf += [ - 'localDomain' => new DatabaseDomain( - $mainConfig->get( 'DBname' ), null, $mainConfig->get( 'DBprefix' ) ), + $class = LBFactoryMW::getLBFactoryClass( $config ); + if ( !isset( $config['readOnlyReason'] ) ) { // TODO: replace the global wfConfiguredReadOnlyReason() with a service. - 'readOnlyReason' => wfConfiguredReadOnlyReason(), - ]; - - $class = LBFactoryMW::getLBFactoryClass( $lbConf ); - if ( $class === 'LBFactorySimple' ) { - if ( is_array( $mainConfig->get( 'DBservers' ) ) ) { - foreach ( $mainConfig->get( 'DBservers' ) as $i => $server ) { - $lbConf['servers'][$i] = $server + [ - 'schema' => $mainConfig->get( 'DBmwschema' ), - 'tablePrefix' => $mainConfig->get( 'DBprefix' ), - 'flags' => DBO_DEFAULT, - 'sqlMode' => $mainConfig->get( 'SQLMode' ), - 'utf8Mode' => $mainConfig->get( 'DBmysql5' ) - ]; - } - } else { - $flags = DBO_DEFAULT; - $flags |= $mainConfig->get( 'DebugDumpSql' ) ? DBO_DEBUG : 0; - $flags |= $mainConfig->get( 'DBssl' ) ? DBO_SSL : 0; - $flags |= $mainConfig->get( 'DBcompress' ) ? DBO_COMPRESS : 0; - $lbConf['servers'] = [ - [ - 'host' => $mainConfig->get( 'DBserver' ), - 'user' => $mainConfig->get( 'DBuser' ), - 'password' => $mainConfig->get( 'DBpassword' ), - 'dbname' => $mainConfig->get( 'DBname' ), - 'schema' => $mainConfig->get( 'DBmwschema' ), - 'tablePrefix' => $mainConfig->get( 'DBprefix' ), - 'type' => $mainConfig->get( 'DBtype' ), - 'load' => 1, - 'flags' => $flags, - 'sqlMode' => $mainConfig->get( 'SQLMode' ), - 'utf8Mode' => $mainConfig->get( 'DBmysql5' ) - ] - ]; - } - $lbConf['externalServers'] = $mainConfig->get( 'ExternalServers' ); + $config['readOnlyReason'] = wfConfiguredReadOnlyReason(); } - return new $class( LBFactoryMW::applyDefaultConfig( $lbConf ) ); + return new $class( $config ); }, 'DBLoadBalancer' => function( MediaWikiServices $services ) { diff --git a/includes/Setup.php b/includes/Setup.php index 7cda14c..ddf5b89 100644 --- a/includes/Setup.php +++ b/includes/Setup.php @@ -504,9 +504,8 @@ // Reset the global service locator, so any services that have already been created will be // re-created while taking into account any custom settings and extensions. MediaWikiServices::resetGlobalInstance( new GlobalVarConfig(), 'quick' ); - +// Apply $wgSharedDB table aliases for the local LB (all non-foreign DB connections) if ( $wgSharedDB && $wgSharedTables ) { - // Apply $wgSharedDB table aliases for the local LB (all non-foreign DB connections) MediaWikiServices::getInstance()->getDBLoadBalancer()->setTableAliases( array_fill_keys( $wgSharedTables, @@ -662,12 +661,6 @@ // initialize the request object in $wgRequest $wgRequest = RequestContext::getMain()->getRequest(); // BackCompat -// Set user IP/agent information for causal consistency purposes -MediaWikiServices::getInstance()->getDBLoadBalancerFactory()->setRequestInfo( [ - 'IPAddress' => $wgRequest->getIP(), - 'UserAgent' => $wgRequest->getHeader( 'User-Agent' ), - 'ChronologyProtection' => $wgRequest->getHeader( 'ChronologyProtection' ) -] ); // Useful debug output if ( $wgCommandLineMode ) { diff --git a/includes/db/loadbalancer/LBFactoryMW.php b/includes/db/loadbalancer/LBFactoryMW.php index 5db7736..1063eef 100644 --- a/includes/db/loadbalancer/LBFactoryMW.php +++ b/includes/db/loadbalancer/LBFactoryMW.php @@ -21,13 +21,15 @@ * @ingroup Database */ +use MediaWiki\MediaWikiServices; +use MediaWiki\Services\DestructibleService; use MediaWiki\Logger\LoggerFactory; /** * Legacy MediaWiki-specific class for generating database load balancers * @ingroup Database */ -abstract class LBFactoryMW extends LBFactory { +abstract class LBFactoryMW extends LBFactory implements DestructibleService { /** @noinspection PhpMissingParentConstructorInspection */ /** * Construct a factory based on a configuration array (typically from $wgLBFactoryConf) @@ -35,15 +37,6 @@ * @TODO: inject objects via dependency framework */ public function __construct( array $conf ) { - parent::__construct( self::applyDefaultConfig( $conf ) ); - } - - /** - * @param array $conf - * @return array - * @TODO: inject objects via dependency framework - */ - public static function applyDefaultConfig( array $conf ) { global $wgCommandLineMode, $wgSQLMode, $wgDBmysql5, $wgDBname, $wgDBprefix; $defaults = [ @@ -55,9 +48,7 @@ 'queryLogger' => LoggerFactory::getInstance( 'wfLogDBError' ), 'connLogger' => LoggerFactory::getInstance( 'wfLogDBError' ), 'perfLogger' => LoggerFactory::getInstance( 'DBPerformance' ), - 'errorLogger' => [ MWExceptionHandler::class, 'logException' ], - 'cliMode' => $wgCommandLineMode, - 'agent' => '' + 'errorLogger' => [ MWExceptionHandler::class, 'logException' ] ]; // Use APC/memcached style caching, but avoids loops with CACHE_DB (T141804) $sCache = ObjectCache::getLocalServerInstance(); @@ -73,12 +64,15 @@ $defaults['wanCache'] = $wCache; } + $this->agent = isset( $params['agent'] ) ? $params['agent'] : ''; + $this->cliMode = isset( $params['cliMode'] ) ? $params['cliMode'] : $wgCommandLineMode; + if ( isset( $conf['serverTemplate'] ) ) { // LBFactoryMulti $conf['serverTemplate']['sqlMode'] = $wgSQLMode; $conf['serverTemplate']['utf8Mode'] = $wgDBmysql5; } - return $conf + $defaults; + parent::__construct( $conf + $defaults ); } /** @@ -110,4 +104,57 @@ return $class; } + + /** + * @return bool + * @since 1.27 + * @deprecated Since 1.28; use laggedReplicaUsed() + */ + public function laggedSlaveUsed() { + return $this->laggedReplicaUsed(); + } + + protected function newChronologyProtector() { + $request = RequestContext::getMain()->getRequest(); + $chronProt = new ChronologyProtector( + ObjectCache::getMainStashInstance(), + [ + 'ip' => $request->getIP(), + 'agent' => $request->getHeader( 'User-Agent' ), + ], + $request->getFloat( 'cpPosTime', $request->getCookie( 'cpPosTime', '' ) ) + ); + if ( PHP_SAPI === 'cli' ) { + $chronProt->setEnabled( false ); + } elseif ( $request->getHeader( 'ChronologyProtection' ) === 'false' ) { + // Request opted out of using position wait logic. This is useful for requests + // done by the job queue or background ETL that do not have a meaningful session. + $chronProt->setWaitEnabled( false ); + } + + return $chronProt; + } + + /** + * Append ?cpPosTime parameter to a URL for ChronologyProtector purposes if needed + * + * Note that unlike cookies, this works accross domains + * + * @param string $url + * @param float $time UNIX timestamp just before shutdown() was called + * @return string + * @since 1.28 + */ + public function appendPreShutdownTimeAsQuery( $url, $time ) { + $usedCluster = 0; + $this->forEachLB( function ( LoadBalancer $lb ) use ( &$usedCluster ) { + $usedCluster |= ( $lb->getServerCount() > 1 ); + } ); + + if ( !$usedCluster ) { + return $url; // no master/replica clusters touched + } + + return wfAppendQuery( $url, [ 'cpPosTime' => $time ] ); + } } diff --git a/includes/db/loadbalancer/LBFactoryMulti.php b/includes/db/loadbalancer/LBFactoryMulti.php index 1f7f528..95bc8f4 100644 --- a/includes/db/loadbalancer/LBFactoryMulti.php +++ b/includes/db/loadbalancer/LBFactoryMulti.php @@ -254,7 +254,7 @@ $section = $this->getSectionForWiki( $wiki ); if ( !isset( $this->mainLBs[$section] ) ) { $lb = $this->newMainLB( $wiki ); - $this->getChronologyProtector()->initLB( $lb ); + $this->chronProt->initLB( $lb ); $this->mainLBs[$section] = $lb; } @@ -295,7 +295,7 @@ public function getExternalLB( $cluster, $wiki = false ) { if ( !isset( $this->extLBs[$cluster] ) ) { $this->extLBs[$cluster] = $this->newExternalLB( $cluster, $wiki ); - $this->getChronologyProtector()->initLB( $this->extLBs[$cluster] ); + $this->chronProt->initLB( $this->extLBs[$cluster] ); } return $this->extLBs[$cluster]; diff --git a/includes/db/loadbalancer/LBFactorySimple.php b/includes/db/loadbalancer/LBFactorySimple.php new file mode 100644 index 0000000..d937ddb --- /dev/null +++ b/includes/db/loadbalancer/LBFactorySimple.php @@ -0,0 +1,172 @@ +<?php +/** + * Generator of database load balancing objects. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * http://www.gnu.org/copyleft/gpl.html + * + * @file + * @ingroup Database + */ + +/** + * A simple single-master LBFactory that gets its configuration from the b/c globals + */ +class LBFactorySimple extends LBFactoryMW { + /** @var LoadBalancer */ + private $mainLB; + /** @var LoadBalancer[] */ + private $extLBs = []; + + /** @var string */ + private $loadMonitorClass; + + public function __construct( array $conf ) { + parent::__construct( $conf ); + + $this->loadMonitorClass = isset( $conf['loadMonitorClass'] ) + ? $conf['loadMonitorClass'] + : null; + } + + /** + * @param bool|string $wiki + * @return LoadBalancer + */ + public function newMainLB( $wiki = false ) { + global $wgDBservers, $wgDBprefix, $wgDBmwschema, $wgSQLMode, $wgDBmysql5; + + if ( is_array( $wgDBservers ) ) { + $servers = $wgDBservers; + foreach ( $servers as $i => &$server ) { + if ( $i == 0 ) { + $server['master'] = true; + } else { + $server['replica'] = true; + } + $server += [ + 'schema' => $wgDBmwschema, + 'tablePrefix' => $wgDBprefix, + 'flags' => DBO_DEFAULT, + 'sqlMode' => $wgSQLMode, + 'utf8Mode' => $wgDBmysql5 + ]; + } + } else { + global $wgDBserver, $wgDBuser, $wgDBpassword, $wgDBname, $wgDBtype, $wgDebugDumpSql; + global $wgDBssl, $wgDBcompress; + + $flags = DBO_DEFAULT; + if ( $wgDebugDumpSql ) { + $flags |= DBO_DEBUG; + } + if ( $wgDBssl ) { + $flags |= DBO_SSL; + } + if ( $wgDBcompress ) { + $flags |= DBO_COMPRESS; + } + + $servers = [ [ + 'host' => $wgDBserver, + 'user' => $wgDBuser, + 'password' => $wgDBpassword, + 'dbname' => $wgDBname, + 'schema' => $wgDBmwschema, + 'tablePrefix' => $wgDBprefix, + 'type' => $wgDBtype, + 'load' => 1, + 'flags' => $flags, + 'master' => true, + 'sqlMode' => $wgSQLMode, + 'utf8Mode' => $wgDBmysql5 + ] ]; + } + + return $this->newLoadBalancer( $servers ); + } + + /** + * @param bool|string $wiki + * @return LoadBalancer + */ + public function getMainLB( $wiki = false ) { + if ( !isset( $this->mainLB ) ) { + $this->mainLB = $this->newMainLB( $wiki ); + $this->chronProt->initLB( $this->mainLB ); + } + + return $this->mainLB; + } + + /** + * @param string $cluster + * @param bool|string $wiki + * @return LoadBalancer + * @throws InvalidArgumentException + */ + protected function newExternalLB( $cluster, $wiki = false ) { + global $wgExternalServers; + if ( !isset( $wgExternalServers[$cluster] ) ) { + throw new InvalidArgumentException( __METHOD__ . ": Unknown cluster \"$cluster\"" ); + } + + return $this->newLoadBalancer( $wgExternalServers[$cluster] ); + } + + /** + * @param string $cluster + * @param bool|string $wiki + * @return array + */ + public function getExternalLB( $cluster, $wiki = false ) { + if ( !isset( $this->extLBs[$cluster] ) ) { + $this->extLBs[$cluster] = $this->newExternalLB( $cluster, $wiki ); + $this->chronProt->initLB( $this->extLBs[$cluster] ); + } + + return $this->extLBs[$cluster]; + } + + private function newLoadBalancer( array $servers ) { + $lb = new LoadBalancer( array_merge( + $this->baseLoadBalancerParams(), + [ + 'servers' => $servers, + 'loadMonitor' => $this->loadMonitorClass, + ] + ) ); + $this->initLoadBalancer( $lb ); + + return $lb; + } + + /** + * Execute a function for each tracked load balancer + * The callback is called with the load balancer as the first parameter, + * and $params passed as the subsequent parameters. + * + * @param callable $callback + * @param array $params + */ + public function forEachLB( $callback, array $params = [] ) { + if ( isset( $this->mainLB ) ) { + call_user_func_array( $callback, array_merge( [ $this->mainLB ], $params ) ); + } + foreach ( $this->extLBs as $lb ) { + call_user_func_array( $callback, array_merge( [ $lb ], $params ) ); + } + } +} diff --git a/includes/libs/rdbms/lbfactory/LBFactory.php b/includes/libs/rdbms/lbfactory/LBFactory.php index 00474fe..a66374b 100644 --- a/includes/libs/rdbms/lbfactory/LBFactory.php +++ b/includes/libs/rdbms/lbfactory/LBFactory.php @@ -55,9 +55,6 @@ protected $localDomain; /** @var string Local hostname of the app server */ protected $hostname; - /** @var array Web request information about the client */ - protected $requestInfo; - /** @var mixed */ protected $ticket; /** @var string|bool String if a requested DBO_TRX transaction round is active */ @@ -106,25 +103,22 @@ : function ( Exception $e ) { trigger_error( E_WARNING, get_class( $e ) . ': ' . $e->getMessage() ); }; + $this->hostname = isset( $conf['hostname'] ) + ? $conf['hostname'] + : gethostname(); - $this->chronProt = isset( $conf['chronProt'] ) ? $conf['chronProt'] : null; + $this->chronProt = isset( $conf['chronProt'] ) + ? $conf['chronProt'] + : $this->newChronologyProtector(); $this->profiler = isset( $params['profiler'] ) ? $params['profiler'] : null; $this->trxProfiler = isset( $conf['trxProfiler'] ) ? $conf['trxProfiler'] : new TransactionProfiler(); - $this->requestInfo = [ - 'IPAddress' => isset( $_SERVER[ 'REMOTE_ADDR' ] ) ? $_SERVER[ 'REMOTE_ADDR' ] : '', - 'UserAgent' => isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : '', - 'ChronologyProtection' => 'true' - ]; - - $this->cliMode = isset( $params['cliMode'] ) ? $params['cliMode'] : PHP_SAPI === 'cli'; - $this->hostname = isset( $conf['hostname'] ) ? $conf['hostname'] : gethostname(); - $this->agent = isset( $params['agent'] ) ? $params['agent'] : ''; - $this->ticket = mt_rand(); + $this->cliMode = isset( $params['cliMode'] ) ? $params['cliMode'] : PHP_SAPI === 'cli'; + $this->agent = isset( $params['agent'] ) ? $params['agent'] : ''; } /** @@ -192,11 +186,10 @@ public function shutdown( $mode = self::SHUTDOWN_CHRONPROT_SYNC, callable $workCallback = null ) { - $chronProt = $this->getChronologyProtector(); if ( $mode === self::SHUTDOWN_CHRONPROT_SYNC ) { - $this->shutdownChronologyProtector( $chronProt, $workCallback, 'sync' ); + $this->shutdownChronologyProtector( $this->chronProt, $workCallback, 'sync' ); } elseif ( $mode === self::SHUTDOWN_CHRONPROT_ASYNC ) { - $this->shutdownChronologyProtector( $chronProt, null, 'async' ); + $this->shutdownChronologyProtector( $this->chronProt, null, 'async' ); } $this->commitMasterChanges( __METHOD__ ); // sanity @@ -547,7 +540,7 @@ * @since 1.28 */ public function getChronologyProtectorTouched( $dbName ) { - return $this->getChronologyProtector()->getTouched( $dbName ); + return $this->chronProt->getTouched( $dbName ); } /** @@ -558,39 +551,27 @@ * @since 1.27 */ public function disableChronologyProtection() { - $this->getChronologyProtector()->setEnabled( false ); + $this->chronProt->setEnabled( false ); } /** * @return ChronologyProtector */ - protected function getChronologyProtector() { - if ( $this->chronProt ) { - return $this->chronProt; - } - - $this->chronProt = new ChronologyProtector( + protected function newChronologyProtector() { + $chronProt = new ChronologyProtector( $this->memCache, [ - 'ip' => $this->requestInfo['IPAddress'], - 'agent' => $this->requestInfo['UserAgent'], + 'ip' => isset( $_SERVER[ 'REMOTE_ADDR' ] ) ? $_SERVER[ 'REMOTE_ADDR' ] : '', + 'agent' => isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : '' ], isset( $_GET['cpPosTime'] ) ? $_GET['cpPosTime'] : null ); - $this->chronProt->setLogger( $this->replLogger ); - + $chronProt->setLogger( $this->replLogger ); if ( $this->cliMode ) { - $this->chronProt->setEnabled( false ); - } elseif ( $this->requestInfo['ChronologyProtection'] === 'false' ) { - // Request opted out of using position wait logic. This is useful for requests - // done by the job queue or background ETL that do not have a meaningful session. - $this->chronProt->setWaitEnabled( false ); + $chronProt->setEnabled( false ); } - $this->replLogger->debug( __METHOD__ . ': using request info ' . - json_encode( $this->requestInfo, JSON_PRETTY_PRINT ) ); - - return $this->chronProt; + return $chronProt; } /** @@ -689,43 +670,5 @@ */ public function setAgentName( $agent ) { $this->agent = $agent; - } - - /** - * Append ?cpPosTime parameter to a URL for ChronologyProtector purposes if needed - * - * Note that unlike cookies, this works accross domains - * - * @param string $url - * @param float $time UNIX timestamp just before shutdown() was called - * @return string - * @since 1.28 - */ - public function appendPreShutdownTimeAsQuery( $url, $time ) { - $usedCluster = 0; - $this->forEachLB( function ( ILoadBalancer $lb ) use ( &$usedCluster ) { - $usedCluster |= ( $lb->getServerCount() > 1 ); - } ); - - if ( !$usedCluster ) { - return $url; // no master/replica clusters touched - } - - return strpos( $url, '?' ) === false ? "$url?cpPosTime=$time" : "$url&cpPosTime=$time"; - } - - /** - * @param array $info Map of fields, including: - * - IPAddress : IP address - * - UserAgent : User-Agent HTTP header - * - ChronologyProtection : cookie/header value specifying ChronologyProtector usage - * @since 1.28 - */ - public function setRequestInfo( array $info ) { - $this->requestInfo = $info + $this->requestInfo; - } - - function __destruct() { - $this->destroy(); } } diff --git a/includes/libs/rdbms/lbfactory/LBFactorySimple.php b/includes/libs/rdbms/lbfactory/LBFactorySimple.php deleted file mode 100644 index 0476cf2..0000000 --- a/includes/libs/rdbms/lbfactory/LBFactorySimple.php +++ /dev/null @@ -1,139 +0,0 @@ -<?php -/** - * Generator of database load balancing objects. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * http://www.gnu.org/copyleft/gpl.html - * - * @file - * @ingroup Database - */ - -/** - * A simple single-master LBFactory that gets its configuration from the b/c globals - */ -class LBFactorySimple extends LBFactory { - /** @var LoadBalancer */ - private $mainLB; - /** @var LoadBalancer[] */ - private $extLBs = []; - - /** @var array[] Map of (server index => server config) */ - private $servers = []; - /** @var array[] Map of (cluster => (server index => server config)) */ - private $externalClusters = []; - - /** @var string */ - private $loadMonitorClass; - - public function __construct( array $conf ) { - parent::__construct( $conf ); - - $this->servers = isset( $conf['servers'] ) ? $conf['servers'] : []; - foreach ( $this->servers as $i => $server ) { - if ( $i == 0 ) { - $this->servers[$i]['master'] = true; - } else { - $this->servers[$i]['replica'] = true; - } - } - - $this->externalClusters = isset( $conf['externalClusters'] ) - ? $conf['externalClusters'] - : []; - $this->loadMonitorClass = isset( $conf['loadMonitorClass'] ) - ? $conf['loadMonitorClass'] - : null; - } - - /** - * @param bool|string $domain - * @return LoadBalancer - */ - public function newMainLB( $domain = false ) { - return $this->newLoadBalancer( $this->servers ); - } - - /** - * @param bool|string $domain - * @return LoadBalancer - */ - public function getMainLB( $domain = false ) { - if ( !isset( $this->mainLB ) ) { - $this->mainLB = $this->newMainLB( $domain ); - $this->getChronologyProtector()->initLB( $this->mainLB ); - } - - return $this->mainLB; - } - - /** - * @param string $cluster - * @param bool|string $domain - * @return LoadBalancer - * @throws InvalidArgumentException - */ - protected function newExternalLB( $cluster, $domain = false ) { - if ( !isset( $this->externalClusters[$cluster] ) ) { - throw new InvalidArgumentException( __METHOD__ . ": Unknown cluster \"$cluster\"" ); - } - - return $this->newLoadBalancer( $this->externalClusters[$cluster] ); - } - - /** - * @param string $cluster - * @param bool|string $domain - * @return array - */ - public function getExternalLB( $cluster, $domain = false ) { - if ( !isset( $this->extLBs[$cluster] ) ) { - $this->extLBs[$cluster] = $this->newExternalLB( $cluster, $domain ); - $this->getChronologyProtector()->initLB( $this->extLBs[$cluster] ); - } - - return $this->extLBs[$cluster]; - } - - private function newLoadBalancer( array $servers ) { - $lb = new LoadBalancer( array_merge( - $this->baseLoadBalancerParams(), - [ - 'servers' => $servers, - 'loadMonitor' => $this->loadMonitorClass, - ] - ) ); - $this->initLoadBalancer( $lb ); - - return $lb; - } - - /** - * Execute a function for each tracked load balancer - * The callback is called with the load balancer as the first parameter, - * and $params passed as the subsequent parameters. - * - * @param callable $callback - * @param array $params - */ - public function forEachLB( $callback, array $params = [] ) { - if ( isset( $this->mainLB ) ) { - call_user_func_array( $callback, array_merge( [ $this->mainLB ], $params ) ); - } - foreach ( $this->extLBs as $lb ) { - call_user_func_array( $callback, array_merge( [ $lb ], $params ) ); - } - } -} diff --git a/tests/phpunit/includes/MediaWikiServicesTest.php b/tests/phpunit/includes/MediaWikiServicesTest.php index 41f516a..8c2b143 100644 --- a/tests/phpunit/includes/MediaWikiServicesTest.php +++ b/tests/phpunit/includes/MediaWikiServicesTest.php @@ -147,6 +147,9 @@ ->disableOriginalConstructor() ->getMock(); + $lbFactory->expects( $this->once() ) + ->method( 'destroy' ); + $newServices->redefineService( 'DBLoadBalancerFactory', function() use ( $lbFactory ) { @@ -161,11 +164,12 @@ try { MediaWikiServices::getInstance()->getService( 'DBLoadBalancerFactory' ); - $this->fail( 'DBLoadBalancerFactory should have been disabled' ); + $this->fail( 'DBLoadBalancerFactory shoudl have been disabled' ); } catch ( ServiceDisabledException $ex ) { // ok, as expected - } catch ( Throwable $ex ) { + } + catch ( Throwable $ex ) { $this->fail( 'ServiceDisabledException expected, caught ' . get_class( $ex ) ); } diff --git a/tests/phpunit/includes/db/LBFactoryTest.php b/tests/phpunit/includes/db/LBFactoryTest.php index adf8a40..cac2d6d 100644 --- a/tests/phpunit/includes/db/LBFactoryTest.php +++ b/tests/phpunit/includes/db/LBFactoryTest.php @@ -58,21 +58,9 @@ } public function testLBFactorySimpleServer() { - global $wgDBserver, $wgDBname, $wgDBuser, $wgDBpassword, $wgDBtype; + $this->setMwGlobals( 'wgDBservers', false ); - $servers = [ - [ - 'host' => $wgDBserver, - 'dbname' => $wgDBname, - 'user' => $wgDBuser, - 'password' => $wgDBpassword, - 'type' => $wgDBtype, - 'load' => 0, - 'flags' => DBO_TRX // REPEATABLE-READ for consistency - ], - ]; - - $factory = new LBFactorySimple( [ 'servers' => $servers ] ); + $factory = new LBFactorySimple( [] ); $lb = $factory->getMainLB(); $dbw = $lb->getConnection( DB_MASTER ); @@ -88,31 +76,28 @@ public function testLBFactorySimpleServers() { global $wgDBserver, $wgDBname, $wgDBuser, $wgDBpassword, $wgDBtype; - $servers = [ + $this->setMwGlobals( 'wgDBservers', [ [ // master - 'host' => $wgDBserver, - 'dbname' => $wgDBname, - 'user' => $wgDBuser, - 'password' => $wgDBpassword, - 'type' => $wgDBtype, - 'load' => 0, - 'flags' => DBO_TRX // REPEATABLE-READ for consistency + 'host' => $wgDBserver, + 'dbname' => $wgDBname, + 'user' => $wgDBuser, + 'password' => $wgDBpassword, + 'type' => $wgDBtype, + 'load' => 0, + 'flags' => DBO_TRX // REPEATABLE-READ for consistency ], [ // emulated slave - 'host' => $wgDBserver, - 'dbname' => $wgDBname, - 'user' => $wgDBuser, - 'password' => $wgDBpassword, - 'type' => $wgDBtype, - 'load' => 100, - 'flags' => DBO_TRX // REPEATABLE-READ for consistency + 'host' => $wgDBserver, + 'dbname' => $wgDBname, + 'user' => $wgDBuser, + 'password' => $wgDBpassword, + 'type' => $wgDBtype, + 'load' => 100, + 'flags' => DBO_TRX // REPEATABLE-READ for consistency ] - ]; - - $factory = new LBFactorySimple( [ - 'servers' => $servers, - 'loadMonitorClass' => 'LoadMonitorNull' ] ); + + $factory = new LBFactorySimple( [ 'loadMonitorClass' => 'LoadMonitorNull' ] ); $lb = $factory->getMainLB(); $dbw = $lb->getConnection( DB_MASTER ); -- To view, visit https://gerrit.wikimedia.org/r/311607 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I918422aeb8b62a443ae8dfd36c902394312fbdd1 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/core Gerrit-Branch: master Gerrit-Owner: Catrope <roan.katt...@gmail.com> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits