Rename LBFactory => LBFactoryMW and make LBFactory in /libs
The former extends the later with MW-specific logic. Also removed a wf* method call from ChronologyProtector. Change-Id: I325f59b7467ab9c2137731d1ce69816f5a020f03
This commit is contained in:
parent
aeedfb8526
commit
0e5cd18b74
11 changed files with 257 additions and 176 deletions
|
|
@ -653,7 +653,8 @@ $wgAutoloadLocalClasses = [
|
||||||
'JsonContentHandler' => __DIR__ . '/includes/content/JsonContentHandler.php',
|
'JsonContentHandler' => __DIR__ . '/includes/content/JsonContentHandler.php',
|
||||||
'KkConverter' => __DIR__ . '/languages/classes/LanguageKk.php',
|
'KkConverter' => __DIR__ . '/languages/classes/LanguageKk.php',
|
||||||
'KuConverter' => __DIR__ . '/languages/classes/LanguageKu.php',
|
'KuConverter' => __DIR__ . '/languages/classes/LanguageKu.php',
|
||||||
'LBFactory' => __DIR__ . '/includes/db/loadbalancer/LBFactory.php',
|
'LBFactory' => __DIR__ . '/includes/libs/rdbms/lbfactory/LBFactory.php',
|
||||||
|
'LBFactoryMW' => __DIR__ . '/includes/db/loadbalancer/LBFactoryMW.php',
|
||||||
'LBFactoryMulti' => __DIR__ . '/includes/db/loadbalancer/LBFactoryMulti.php',
|
'LBFactoryMulti' => __DIR__ . '/includes/db/loadbalancer/LBFactoryMulti.php',
|
||||||
'LBFactorySimple' => __DIR__ . '/includes/db/loadbalancer/LBFactorySimple.php',
|
'LBFactorySimple' => __DIR__ . '/includes/db/loadbalancer/LBFactorySimple.php',
|
||||||
'LBFactorySingle' => __DIR__ . '/includes/db/loadbalancer/LBFactorySingle.php',
|
'LBFactorySingle' => __DIR__ . '/includes/db/loadbalancer/LBFactorySingle.php',
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ return [
|
||||||
'DBLoadBalancerFactory' => function( MediaWikiServices $services ) {
|
'DBLoadBalancerFactory' => function( MediaWikiServices $services ) {
|
||||||
$config = $services->getMainConfig()->get( 'LBFactoryConf' );
|
$config = $services->getMainConfig()->get( 'LBFactoryConf' );
|
||||||
|
|
||||||
$class = LBFactory::getLBFactoryClass( $config );
|
$class = LBFactoryMW::getLBFactoryClass( $config );
|
||||||
if ( !isset( $config['readOnlyReason'] ) ) {
|
if ( !isset( $config['readOnlyReason'] ) ) {
|
||||||
// TODO: replace the global wfConfiguredReadOnlyReason() with a service.
|
// TODO: replace the global wfConfiguredReadOnlyReason() with a service.
|
||||||
$config['readOnlyReason'] = wfConfiguredReadOnlyReason();
|
$config['readOnlyReason'] = wfConfiguredReadOnlyReason();
|
||||||
|
|
|
||||||
|
|
@ -129,7 +129,10 @@ class CloneDatabase {
|
||||||
*/
|
*/
|
||||||
public static function changePrefix( $prefix ) {
|
public static function changePrefix( $prefix ) {
|
||||||
global $wgDBprefix;
|
global $wgDBprefix;
|
||||||
wfGetLBFactory()->forEachLB( function( LoadBalancer $lb ) use ( $prefix ) {
|
|
||||||
|
$lbFactory = wfGetLBFactory();
|
||||||
|
$lbFactory->setDomainPrefix( $prefix );
|
||||||
|
$lbFactory->forEachLB( function( LoadBalancer $lb ) use ( $prefix ) {
|
||||||
$lb->setDomainPrefix( $prefix );
|
$lb->setDomainPrefix( $prefix );
|
||||||
$lb->forEachOpenConnection( function ( IDatabase $db ) use ( $prefix ) {
|
$lb->forEachOpenConnection( function ( IDatabase $db ) use ( $prefix ) {
|
||||||
$db->tablePrefix( $prefix );
|
$db->tablePrefix( $prefix );
|
||||||
|
|
|
||||||
149
includes/db/loadbalancer/LBFactoryMW.php
Normal file
149
includes/db/loadbalancer/LBFactoryMW.php
Normal file
|
|
@ -0,0 +1,149 @@
|
||||||
|
<?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
|
||||||
|
*/
|
||||||
|
|
||||||
|
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 implements DestructibleService {
|
||||||
|
/** @noinspection PhpMissingParentConstructorInspection */
|
||||||
|
/**
|
||||||
|
* Construct a factory based on a configuration array (typically from $wgLBFactoryConf)
|
||||||
|
* @param array $conf
|
||||||
|
* @TODO: inject objects via dependency framework
|
||||||
|
*/
|
||||||
|
public function __construct( array $conf ) {
|
||||||
|
$defaults = [
|
||||||
|
'domain' => wfWikiID(),
|
||||||
|
'hostname' => wfHostname(),
|
||||||
|
'trxProfiler' => Profiler::instance()->getTransactionProfiler(),
|
||||||
|
'replLogger' => LoggerFactory::getInstance( 'DBReplication' ),
|
||||||
|
'queryLogger' => LoggerFactory::getInstance( 'wfLogDBError' ),
|
||||||
|
'connLogger' => LoggerFactory::getInstance( 'wfLogDBError' ),
|
||||||
|
'perfLogger' => LoggerFactory::getInstance( 'DBPerformance' ),
|
||||||
|
'errorLogger' => [ MWExceptionHandler::class, 'logException' ]
|
||||||
|
];
|
||||||
|
// Use APC/memcached style caching, but avoids loops with CACHE_DB (T141804)
|
||||||
|
$sCache = ObjectCache::getLocalServerInstance();
|
||||||
|
if ( $sCache->getQoS( $sCache::ATTR_EMULATION ) > $sCache::QOS_EMULATION_SQL ) {
|
||||||
|
$defaults['srvCache'] = $sCache;
|
||||||
|
}
|
||||||
|
$cCache = ObjectCache::getLocalClusterInstance();
|
||||||
|
if ( $cCache->getQoS( $cCache::ATTR_EMULATION ) > $cCache::QOS_EMULATION_SQL ) {
|
||||||
|
$defaults['memCache'] = $cCache;
|
||||||
|
}
|
||||||
|
$wCache = ObjectCache::getMainWANInstance();
|
||||||
|
if ( $wCache->getQoS( $wCache::ATTR_EMULATION ) > $wCache::QOS_EMULATION_SQL ) {
|
||||||
|
$defaults['wanCache'] = $wCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
parent::__construct( $conf + $defaults );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the LBFactory class to use and the load balancer configuration.
|
||||||
|
*
|
||||||
|
* @todo instead of this, use a ServiceContainer for managing the different implementations.
|
||||||
|
*
|
||||||
|
* @param array $config (e.g. $wgLBFactoryConf)
|
||||||
|
* @return string Class name
|
||||||
|
*/
|
||||||
|
public static function getLBFactoryClass( array $config ) {
|
||||||
|
// For configuration backward compatibility after removing
|
||||||
|
// underscores from class names in MediaWiki 1.23.
|
||||||
|
$bcClasses = [
|
||||||
|
'LBFactory_Simple' => 'LBFactorySimple',
|
||||||
|
'LBFactory_Single' => 'LBFactorySingle',
|
||||||
|
'LBFactory_Multi' => 'LBFactoryMulti'
|
||||||
|
];
|
||||||
|
|
||||||
|
$class = $config['class'];
|
||||||
|
|
||||||
|
if ( isset( $bcClasses[$class] ) ) {
|
||||||
|
$class = $bcClasses[$class];
|
||||||
|
wfDeprecated(
|
||||||
|
'$wgLBFactoryConf must be updated. See RELEASE-NOTES for details',
|
||||||
|
'1.23'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 ] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -83,7 +83,7 @@
|
||||||
*
|
*
|
||||||
* @ingroup Database
|
* @ingroup Database
|
||||||
*/
|
*/
|
||||||
class LBFactoryMulti extends LBFactory {
|
class LBFactoryMulti extends LBFactoryMW {
|
||||||
/** @var array A map of database names to section names */
|
/** @var array A map of database names to section names */
|
||||||
private $sectionsByDB;
|
private $sectionsByDB;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@
|
||||||
/**
|
/**
|
||||||
* A simple single-master LBFactory that gets its configuration from the b/c globals
|
* A simple single-master LBFactory that gets its configuration from the b/c globals
|
||||||
*/
|
*/
|
||||||
class LBFactorySimple extends LBFactory {
|
class LBFactorySimple extends LBFactoryMW {
|
||||||
/** @var LoadBalancer */
|
/** @var LoadBalancer */
|
||||||
private $mainLB;
|
private $mainLB;
|
||||||
/** @var LoadBalancer[] */
|
/** @var LoadBalancer[] */
|
||||||
|
|
|
||||||
|
|
@ -96,17 +96,17 @@ class ChronologyProtector implements LoggerAwareInterface{
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialise a LoadBalancer to give it appropriate chronology protection.
|
* Initialise a ILoadBalancer to give it appropriate chronology protection.
|
||||||
*
|
*
|
||||||
* If the stash has a previous master position recorded, this will try to
|
* If the stash has a previous master position recorded, this will try to
|
||||||
* make sure that the next query to a replica DB of that master will see changes up
|
* make sure that the next query to a replica DB of that master will see changes up
|
||||||
* to that position by delaying execution. The delay may timeout and allow stale
|
* to that position by delaying execution. The delay may timeout and allow stale
|
||||||
* data if no non-lagged replica DBs are available.
|
* data if no non-lagged replica DBs are available.
|
||||||
*
|
*
|
||||||
* @param LoadBalancer $lb
|
* @param ILoadBalancer $lb
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function initLB( LoadBalancer $lb ) {
|
public function initLB( ILoadBalancer $lb ) {
|
||||||
if ( !$this->enabled || $lb->getServerCount() <= 1 ) {
|
if ( !$this->enabled || $lb->getServerCount() <= 1 ) {
|
||||||
return; // non-replicated setup or disabled
|
return; // non-replicated setup or disabled
|
||||||
}
|
}
|
||||||
|
|
@ -122,13 +122,13 @@ class ChronologyProtector implements LoggerAwareInterface{
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notify the ChronologyProtector that the LoadBalancer is about to shut
|
* Notify the ChronologyProtector that the ILoadBalancer is about to shut
|
||||||
* down. Saves replication positions.
|
* down. Saves replication positions.
|
||||||
*
|
*
|
||||||
* @param LoadBalancer $lb
|
* @param ILoadBalancer $lb
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function shutdownLB( LoadBalancer $lb ) {
|
public function shutdownLB( ILoadBalancer $lb ) {
|
||||||
if ( !$this->enabled ) {
|
if ( !$this->enabled ) {
|
||||||
return; // not enabled
|
return; // not enabled
|
||||||
} elseif ( !$lb->hasOrMadeRecentMasterChanges( INF ) ) {
|
} elseif ( !$lb->hasOrMadeRecentMasterChanges( INF ) ) {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* Generator of database load balancing objects.
|
* Generator and manager of database load balancing objects
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|
@ -22,23 +22,26 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Psr\Log\LoggerInterface;
|
use Psr\Log\LoggerInterface;
|
||||||
use MediaWiki\MediaWikiServices;
|
|
||||||
use MediaWiki\Services\DestructibleService;
|
|
||||||
use MediaWiki\Logger\LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An interface for generating database load balancers
|
* An interface for generating database load balancers
|
||||||
* @ingroup Database
|
* @ingroup Database
|
||||||
*/
|
*/
|
||||||
abstract class LBFactory implements DestructibleService {
|
abstract class LBFactory {
|
||||||
/** @var ChronologyProtector */
|
/** @var ChronologyProtector */
|
||||||
protected $chronProt;
|
protected $chronProt;
|
||||||
/** @var TransactionProfiler */
|
/** @var TransactionProfiler */
|
||||||
protected $trxProfiler;
|
protected $trxProfiler;
|
||||||
/** @var LoggerInterface */
|
/** @var LoggerInterface */
|
||||||
protected $trxLogger;
|
|
||||||
/** @var LoggerInterface */
|
|
||||||
protected $replLogger;
|
protected $replLogger;
|
||||||
|
/** @var LoggerInterface */
|
||||||
|
protected $connLogger;
|
||||||
|
/** @var LoggerInterface */
|
||||||
|
protected $queryLogger;
|
||||||
|
/** @var LoggerInterface */
|
||||||
|
protected $perfLogger;
|
||||||
|
/** @var callable Error logger */
|
||||||
|
protected $errorLogger;
|
||||||
/** @var BagOStuff */
|
/** @var BagOStuff */
|
||||||
protected $srvCache;
|
protected $srvCache;
|
||||||
/** @var BagOStuff */
|
/** @var BagOStuff */
|
||||||
|
|
@ -46,6 +49,10 @@ abstract class LBFactory implements DestructibleService {
|
||||||
/** @var WANObjectCache */
|
/** @var WANObjectCache */
|
||||||
protected $wanCache;
|
protected $wanCache;
|
||||||
|
|
||||||
|
/** @var string Local domain */
|
||||||
|
protected $domain;
|
||||||
|
/** @var string Local hostname of the app server */
|
||||||
|
protected $hostname;
|
||||||
/** @var mixed */
|
/** @var mixed */
|
||||||
protected $ticket;
|
protected $ticket;
|
||||||
/** @var string|bool String if a requested DBO_TRX transaction round is active */
|
/** @var string|bool String if a requested DBO_TRX transaction round is active */
|
||||||
|
|
@ -59,38 +66,44 @@ abstract class LBFactory implements DestructibleService {
|
||||||
const SHUTDOWN_CHRONPROT_ASYNC = 1; // save DB positions, but don't wait on remote DCs
|
const SHUTDOWN_CHRONPROT_ASYNC = 1; // save DB positions, but don't wait on remote DCs
|
||||||
const SHUTDOWN_CHRONPROT_SYNC = 2; // save DB positions, waiting on all DCs
|
const SHUTDOWN_CHRONPROT_SYNC = 2; // save DB positions, waiting on all DCs
|
||||||
|
|
||||||
|
private static $loggerFields =
|
||||||
|
[ 'replLogger', 'connLogger', 'queryLogger', 'perfLogger' ];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a factory based on a configuration array (typically from $wgLBFactoryConf)
|
* @TODO: document base params here
|
||||||
* @param array $conf
|
* @param array $conf
|
||||||
* @TODO: inject objects via dependency framework
|
|
||||||
*/
|
*/
|
||||||
public function __construct( array $conf ) {
|
public function __construct( array $conf ) {
|
||||||
|
$this->domain = isset( $conf['domain'] ) ? $conf['domain'] : '';
|
||||||
if ( isset( $conf['readOnlyReason'] ) && is_string( $conf['readOnlyReason'] ) ) {
|
if ( isset( $conf['readOnlyReason'] ) && is_string( $conf['readOnlyReason'] ) ) {
|
||||||
$this->readOnlyReason = $conf['readOnlyReason'];
|
$this->readOnlyReason = $conf['readOnlyReason'];
|
||||||
}
|
}
|
||||||
// Use APC/memcached style caching, but avoids loops with CACHE_DB (T141804)
|
|
||||||
$sCache = ObjectCache::getLocalServerInstance();
|
$this->srvCache = isset( $conf['srvCache'] ) ? $conf['srvCache'] : new EmptyBagOStuff();
|
||||||
if ( $sCache->getQoS( $sCache::ATTR_EMULATION ) > $sCache::QOS_EMULATION_SQL ) {
|
$this->memCache = isset( $conf['memCache'] ) ? $conf['memCache'] : new EmptyBagOStuff();
|
||||||
$this->srvCache = $sCache;
|
$this->wanCache = isset( $conf['wanCache'] )
|
||||||
} else {
|
? $conf['wanCache']
|
||||||
$this->srvCache = new EmptyBagOStuff();
|
: WANObjectCache::newEmpty();
|
||||||
|
|
||||||
|
foreach ( self::$loggerFields as $key ) {
|
||||||
|
$this->$key = isset( $conf[$key] ) ? $conf[$key] : new \Psr\Log\NullLogger();
|
||||||
}
|
}
|
||||||
$cCache = ObjectCache::getLocalClusterInstance();
|
$this->errorLogger = isset( $conf['errorLogger'] )
|
||||||
if ( $cCache->getQoS( $cCache::ATTR_EMULATION ) > $cCache::QOS_EMULATION_SQL ) {
|
? $conf['errorLogger']
|
||||||
$this->memCache = $cCache;
|
: function ( Exception $e ) {
|
||||||
} else {
|
trigger_error( E_WARNING, $e->getMessage() );
|
||||||
$this->memCache = new EmptyBagOStuff();
|
};
|
||||||
}
|
$this->hostname = isset( $conf['hostname'] )
|
||||||
$wCache = ObjectCache::getMainWANInstance();
|
? $conf['hostname']
|
||||||
if ( $wCache->getQoS( $wCache::ATTR_EMULATION ) > $wCache::QOS_EMULATION_SQL ) {
|
: gethostname();
|
||||||
$this->wanCache = $wCache;
|
|
||||||
} else {
|
$this->chronProt = isset( $conf['chronProt'] )
|
||||||
$this->wanCache = WANObjectCache::newEmpty();
|
? $conf['chronProt']
|
||||||
}
|
: $this->newChronologyProtector();
|
||||||
$this->trxProfiler = Profiler::instance()->getTransactionProfiler();
|
$this->trxProfiler = isset( $conf['trxProfiler'] )
|
||||||
$this->trxLogger = LoggerFactory::getInstance( 'DBTransaction' );
|
? $conf['trxProfiler']
|
||||||
$this->replLogger = LoggerFactory::getInstance( 'DBReplication' );
|
: new TransactionProfiler();
|
||||||
$this->chronProt = $this->newChronologyProtector();
|
|
||||||
$this->ticket = mt_rand();
|
$this->ticket = mt_rand();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -104,80 +117,22 @@ abstract class LBFactory implements DestructibleService {
|
||||||
$this->forEachLBCallMethod( 'disable' );
|
$this->forEachLBCallMethod( 'disable' );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Disables all access to the load balancer, will cause all database access
|
|
||||||
* to throw a DBAccessError
|
|
||||||
*/
|
|
||||||
public static function disableBackend() {
|
|
||||||
MediaWikiServices::disableStorageBackend();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get an LBFactory instance
|
|
||||||
*
|
|
||||||
* @deprecated since 1.27, use MediaWikiServices::getDBLoadBalancerFactory() instead.
|
|
||||||
*
|
|
||||||
* @return LBFactory
|
|
||||||
*/
|
|
||||||
public static function singleton() {
|
|
||||||
return MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the LBFactory class to use and the load balancer configuration.
|
|
||||||
*
|
|
||||||
* @todo instead of this, use a ServiceContainer for managing the different implementations.
|
|
||||||
*
|
|
||||||
* @param array $config (e.g. $wgLBFactoryConf)
|
|
||||||
* @return string Class name
|
|
||||||
*/
|
|
||||||
public static function getLBFactoryClass( array $config ) {
|
|
||||||
// For configuration backward compatibility after removing
|
|
||||||
// underscores from class names in MediaWiki 1.23.
|
|
||||||
$bcClasses = [
|
|
||||||
'LBFactory_Simple' => 'LBFactorySimple',
|
|
||||||
'LBFactory_Single' => 'LBFactorySingle',
|
|
||||||
'LBFactory_Multi' => 'LBFactoryMulti',
|
|
||||||
];
|
|
||||||
|
|
||||||
$class = $config['class'];
|
|
||||||
|
|
||||||
if ( isset( $bcClasses[$class] ) ) {
|
|
||||||
$class = $bcClasses[$class];
|
|
||||||
wfDeprecated(
|
|
||||||
'$wgLBFactoryConf must be updated. See RELEASE-NOTES for details',
|
|
||||||
'1.23'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $class;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shut down, close connections and destroy the cached instance.
|
|
||||||
*
|
|
||||||
* @deprecated since 1.27, use LBFactory::destroy()
|
|
||||||
*/
|
|
||||||
public static function destroyInstance() {
|
|
||||||
MediaWikiServices::getInstance()->getDBLoadBalancerFactory()->destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new load balancer object. The resulting object will be untracked,
|
* Create a new load balancer object. The resulting object will be untracked,
|
||||||
* not chronology-protected, and the caller is responsible for cleaning it up.
|
* not chronology-protected, and the caller is responsible for cleaning it up.
|
||||||
*
|
*
|
||||||
* @param bool|string $wiki Wiki ID, or false for the current wiki
|
* @param bool|string $domain Wiki ID, or false for the current wiki
|
||||||
* @return LoadBalancer
|
* @return ILoadBalancer
|
||||||
*/
|
*/
|
||||||
abstract public function newMainLB( $wiki = false );
|
abstract public function newMainLB( $domain = false );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a cached (tracked) load balancer object.
|
* Get a cached (tracked) load balancer object.
|
||||||
*
|
*
|
||||||
* @param bool|string $wiki Wiki ID, or false for the current wiki
|
* @param bool|string $domain Wiki ID, or false for the current wiki
|
||||||
* @return LoadBalancer
|
* @return ILoadBalancer
|
||||||
*/
|
*/
|
||||||
abstract public function getMainLB( $wiki = false );
|
abstract public function getMainLB( $domain = false );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new load balancer for external storage. The resulting object will be
|
* Create a new load balancer for external storage. The resulting object will be
|
||||||
|
|
@ -185,19 +140,19 @@ abstract class LBFactory implements DestructibleService {
|
||||||
* cleaning it up.
|
* cleaning it up.
|
||||||
*
|
*
|
||||||
* @param string $cluster External storage cluster, or false for core
|
* @param string $cluster External storage cluster, or false for core
|
||||||
* @param bool|string $wiki Wiki ID, or false for the current wiki
|
* @param bool|string $domain Wiki ID, or false for the current wiki
|
||||||
* @return LoadBalancer
|
* @return ILoadBalancer
|
||||||
*/
|
*/
|
||||||
abstract protected function newExternalLB( $cluster, $wiki = false );
|
abstract protected function newExternalLB( $cluster, $domain = false );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a cached (tracked) load balancer for external storage
|
* Get a cached (tracked) load balancer for external storage
|
||||||
*
|
*
|
||||||
* @param string $cluster External storage cluster, or false for core
|
* @param string $cluster External storage cluster, or false for core
|
||||||
* @param bool|string $wiki Wiki ID, or false for the current wiki
|
* @param bool|string $domain Wiki ID, or false for the current wiki
|
||||||
* @return LoadBalancer
|
* @return ILoadBalancer
|
||||||
*/
|
*/
|
||||||
abstract public function getExternalLB( $cluster, $wiki = false );
|
abstract public function getExternalLB( $cluster, $domain = false );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute a function for each tracked load balancer
|
* Execute a function for each tracked load balancer
|
||||||
|
|
@ -232,9 +187,9 @@ abstract class LBFactory implements DestructibleService {
|
||||||
* @param string $methodName
|
* @param string $methodName
|
||||||
* @param array $args
|
* @param array $args
|
||||||
*/
|
*/
|
||||||
private function forEachLBCallMethod( $methodName, array $args = [] ) {
|
protected function forEachLBCallMethod( $methodName, array $args = [] ) {
|
||||||
$this->forEachLB(
|
$this->forEachLB(
|
||||||
function ( LoadBalancer $loadBalancer, $methodName, array $args ) {
|
function ( ILoadBalancer $loadBalancer, $methodName, array $args ) {
|
||||||
call_user_func_array( [ $loadBalancer, $methodName ], $args );
|
call_user_func_array( [ $loadBalancer, $methodName ], $args );
|
||||||
},
|
},
|
||||||
[ $methodName, $args ]
|
[ $methodName, $args ]
|
||||||
|
|
@ -316,7 +271,7 @@ abstract class LBFactory implements DestructibleService {
|
||||||
// Run all post-commit callbacks
|
// Run all post-commit callbacks
|
||||||
/** @var Exception $e */
|
/** @var Exception $e */
|
||||||
$e = null; // first callback exception
|
$e = null; // first callback exception
|
||||||
$this->forEachLB( function ( LoadBalancer $lb ) use ( &$e ) {
|
$this->forEachLB( function ( ILoadBalancer $lb ) use ( &$e ) {
|
||||||
$ex = $lb->runMasterPostTrxCallbacks( IDatabase::TRIGGER_COMMIT );
|
$ex = $lb->runMasterPostTrxCallbacks( IDatabase::TRIGGER_COMMIT );
|
||||||
$e = $e ?: $ex;
|
$e = $e ?: $ex;
|
||||||
} );
|
} );
|
||||||
|
|
@ -338,7 +293,7 @@ abstract class LBFactory implements DestructibleService {
|
||||||
$this->forEachLBCallMethod( 'suppressTransactionEndCallbacks' );
|
$this->forEachLBCallMethod( 'suppressTransactionEndCallbacks' );
|
||||||
$this->forEachLBCallMethod( 'rollbackMasterChanges', [ $fname ] );
|
$this->forEachLBCallMethod( 'rollbackMasterChanges', [ $fname ] );
|
||||||
// Run all post-rollback callbacks
|
// Run all post-rollback callbacks
|
||||||
$this->forEachLB( function ( LoadBalancer $lb ) {
|
$this->forEachLB( function ( ILoadBalancer $lb ) {
|
||||||
$lb->runMasterPostTrxCallbacks( IDatabase::TRIGGER_ROLLBACK );
|
$lb->runMasterPostTrxCallbacks( IDatabase::TRIGGER_ROLLBACK );
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
@ -348,7 +303,7 @@ abstract class LBFactory implements DestructibleService {
|
||||||
*/
|
*/
|
||||||
private function logIfMultiDbTransaction() {
|
private function logIfMultiDbTransaction() {
|
||||||
$callersByDB = [];
|
$callersByDB = [];
|
||||||
$this->forEachLB( function ( LoadBalancer $lb ) use ( &$callersByDB ) {
|
$this->forEachLB( function ( ILoadBalancer $lb ) use ( &$callersByDB ) {
|
||||||
$masterName = $lb->getServerName( $lb->getWriterIndex() );
|
$masterName = $lb->getServerName( $lb->getWriterIndex() );
|
||||||
$callers = $lb->pendingMasterChangeCallers();
|
$callers = $lb->pendingMasterChangeCallers();
|
||||||
if ( $callers ) {
|
if ( $callers ) {
|
||||||
|
|
@ -362,7 +317,7 @@ abstract class LBFactory implements DestructibleService {
|
||||||
foreach ( $callersByDB as $db => $callers ) {
|
foreach ( $callersByDB as $db => $callers ) {
|
||||||
$msg .= "$db: " . implode( '; ', $callers ) . "\n";
|
$msg .= "$db: " . implode( '; ', $callers ) . "\n";
|
||||||
}
|
}
|
||||||
$this->trxLogger->info( $msg );
|
$this->queryLogger->info( $msg );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -373,7 +328,7 @@ abstract class LBFactory implements DestructibleService {
|
||||||
*/
|
*/
|
||||||
public function hasMasterChanges() {
|
public function hasMasterChanges() {
|
||||||
$ret = false;
|
$ret = false;
|
||||||
$this->forEachLB( function ( LoadBalancer $lb ) use ( &$ret ) {
|
$this->forEachLB( function ( ILoadBalancer $lb ) use ( &$ret ) {
|
||||||
$ret = $ret || $lb->hasMasterChanges();
|
$ret = $ret || $lb->hasMasterChanges();
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
|
@ -387,22 +342,13 @@ abstract class LBFactory implements DestructibleService {
|
||||||
*/
|
*/
|
||||||
public function laggedReplicaUsed() {
|
public function laggedReplicaUsed() {
|
||||||
$ret = false;
|
$ret = false;
|
||||||
$this->forEachLB( function ( LoadBalancer $lb ) use ( &$ret ) {
|
$this->forEachLB( function ( ILoadBalancer $lb ) use ( &$ret ) {
|
||||||
$ret = $ret || $lb->laggedReplicaUsed();
|
$ret = $ret || $lb->laggedReplicaUsed();
|
||||||
} );
|
} );
|
||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return bool
|
|
||||||
* @since 1.27
|
|
||||||
* @deprecated Since 1.28; use laggedReplicaUsed()
|
|
||||||
*/
|
|
||||||
public function laggedSlaveUsed() {
|
|
||||||
return $this->laggedReplicaUsed();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if any master connection has pending/written changes from this request
|
* Determine if any master connection has pending/written changes from this request
|
||||||
* @param float $age How many seconds ago is "recent" [defaults to LB lag wait timeout]
|
* @param float $age How many seconds ago is "recent" [defaults to LB lag wait timeout]
|
||||||
|
|
@ -411,7 +357,7 @@ abstract class LBFactory implements DestructibleService {
|
||||||
*/
|
*/
|
||||||
public function hasOrMadeRecentMasterChanges( $age = null ) {
|
public function hasOrMadeRecentMasterChanges( $age = null ) {
|
||||||
$ret = false;
|
$ret = false;
|
||||||
$this->forEachLB( function ( LoadBalancer $lb ) use ( $age, &$ret ) {
|
$this->forEachLB( function ( ILoadBalancer $lb ) use ( $age, &$ret ) {
|
||||||
$ret = $ret || $lb->hasOrMadeRecentMasterChanges( $age );
|
$ret = $ret || $lb->hasOrMadeRecentMasterChanges( $age );
|
||||||
} );
|
} );
|
||||||
return $ret;
|
return $ret;
|
||||||
|
|
@ -450,14 +396,14 @@ abstract class LBFactory implements DestructibleService {
|
||||||
];
|
];
|
||||||
|
|
||||||
// Figure out which clusters need to be checked
|
// Figure out which clusters need to be checked
|
||||||
/** @var LoadBalancer[] $lbs */
|
/** @var ILoadBalancer[] $lbs */
|
||||||
$lbs = [];
|
$lbs = [];
|
||||||
if ( $opts['cluster'] !== false ) {
|
if ( $opts['cluster'] !== false ) {
|
||||||
$lbs[] = $this->getExternalLB( $opts['cluster'] );
|
$lbs[] = $this->getExternalLB( $opts['cluster'] );
|
||||||
} elseif ( $opts['wiki'] !== false ) {
|
} elseif ( $opts['wiki'] !== false ) {
|
||||||
$lbs[] = $this->getMainLB( $opts['wiki'] );
|
$lbs[] = $this->getMainLB( $opts['wiki'] );
|
||||||
} else {
|
} else {
|
||||||
$this->forEachLB( function ( LoadBalancer $lb ) use ( &$lbs ) {
|
$this->forEachLB( function ( ILoadBalancer $lb ) use ( &$lbs ) {
|
||||||
$lbs[] = $lb;
|
$lbs[] = $lb;
|
||||||
} );
|
} );
|
||||||
if ( !$lbs ) {
|
if ( !$lbs ) {
|
||||||
|
|
@ -533,7 +479,7 @@ abstract class LBFactory implements DestructibleService {
|
||||||
*/
|
*/
|
||||||
public function getEmptyTransactionTicket( $fname ) {
|
public function getEmptyTransactionTicket( $fname ) {
|
||||||
if ( $this->hasMasterChanges() ) {
|
if ( $this->hasMasterChanges() ) {
|
||||||
$this->trxLogger->error( __METHOD__ . ": $fname does not have outer scope." );
|
$this->queryLogger->error( __METHOD__ . ": $fname does not have outer scope." );
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -553,15 +499,14 @@ abstract class LBFactory implements DestructibleService {
|
||||||
*/
|
*/
|
||||||
public function commitAndWaitForReplication( $fname, $ticket, array $opts = [] ) {
|
public function commitAndWaitForReplication( $fname, $ticket, array $opts = [] ) {
|
||||||
if ( $ticket !== $this->ticket ) {
|
if ( $ticket !== $this->ticket ) {
|
||||||
$logger = LoggerFactory::getInstance( 'DBPerformance' );
|
$this->perfLogger->error( __METHOD__ . ": $fname does not have outer scope." );
|
||||||
$logger->error( __METHOD__ . ": cannot commit; $fname does not have outer scope." );
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The transaction owner and any caller with the empty transaction ticket can commit
|
// The transaction owner and any caller with the empty transaction ticket can commit
|
||||||
// so that getEmptyTransactionTicket() callers don't risk seeing DBTransactionError.
|
// so that getEmptyTransactionTicket() callers don't risk seeing DBTransactionError.
|
||||||
if ( $this->trxRoundId !== false && $fname !== $this->trxRoundId ) {
|
if ( $this->trxRoundId !== false && $fname !== $this->trxRoundId ) {
|
||||||
$this->trxLogger->info( "$fname: committing on behalf of {$this->trxRoundId}." );
|
$this->queryLogger->info( "$fname: committing on behalf of {$this->trxRoundId}." );
|
||||||
$fnameEffective = $this->trxRoundId;
|
$fnameEffective = $this->trxRoundId;
|
||||||
} else {
|
} else {
|
||||||
$fnameEffective = $fname;
|
$fnameEffective = $fname;
|
||||||
|
|
@ -600,22 +545,17 @@ abstract class LBFactory implements DestructibleService {
|
||||||
* @return ChronologyProtector
|
* @return ChronologyProtector
|
||||||
*/
|
*/
|
||||||
protected function newChronologyProtector() {
|
protected function newChronologyProtector() {
|
||||||
$request = RequestContext::getMain()->getRequest();
|
|
||||||
$chronProt = new ChronologyProtector(
|
$chronProt = new ChronologyProtector(
|
||||||
ObjectCache::getMainStashInstance(),
|
$this->memCache,
|
||||||
[
|
[
|
||||||
'ip' => $request->getIP(),
|
'ip' => isset( $_SERVER[ 'REMOTE_ADDR' ] ) ? $_SERVER[ 'REMOTE_ADDR' ] : '',
|
||||||
'agent' => $request->getHeader( 'User-Agent' ),
|
'agent' => isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : ''
|
||||||
],
|
],
|
||||||
$request->getFloat( 'cpPosTime', $request->getCookie( 'cpPosTime', '' ) )
|
isset( $_GET['cpPosTime'] ) ? $_GET['cpPosTime'] : null
|
||||||
);
|
);
|
||||||
$chronProt->setLogger( $this->replLogger );
|
$chronProt->setLogger( $this->replLogger );
|
||||||
if ( PHP_SAPI === 'cli' ) {
|
if ( PHP_SAPI === 'cli' ) {
|
||||||
$chronProt->setEnabled( false );
|
$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;
|
return $chronProt;
|
||||||
|
|
@ -632,7 +572,7 @@ abstract class LBFactory implements DestructibleService {
|
||||||
ChronologyProtector $cp, $workCallback, $mode
|
ChronologyProtector $cp, $workCallback, $mode
|
||||||
) {
|
) {
|
||||||
// Record all the master positions needed
|
// Record all the master positions needed
|
||||||
$this->forEachLB( function ( LoadBalancer $lb ) use ( $cp ) {
|
$this->forEachLB( function ( ILoadBalancer $lb ) use ( $cp ) {
|
||||||
$cp->shutdownLB( $lb );
|
$cp->shutdownLB( $lb );
|
||||||
} );
|
} );
|
||||||
// Write them to the persistent stash. Try to do something useful by running $work
|
// Write them to the persistent stash. Try to do something useful by running $work
|
||||||
|
|
@ -646,7 +586,7 @@ abstract class LBFactory implements DestructibleService {
|
||||||
// replica DBs to catch up before responding. Even if there are several DCs, this increases
|
// replica DBs to catch up before responding. Even if there are several DCs, this increases
|
||||||
// the chance that the user will see their own changes immediately afterwards. As long
|
// the chance that the user will see their own changes immediately afterwards. As long
|
||||||
// as the sticky DC cookie applies (same domain), this is not even an issue.
|
// as the sticky DC cookie applies (same domain), this is not even an issue.
|
||||||
$this->forEachLB( function ( LoadBalancer $lb ) use ( $unsavedPositions ) {
|
$this->forEachLB( function ( ILoadBalancer $lb ) use ( $unsavedPositions ) {
|
||||||
$masterName = $lb->getServerName( $lb->getWriterIndex() );
|
$masterName = $lb->getServerName( $lb->getWriterIndex() );
|
||||||
if ( isset( $unsavedPositions[$masterName] ) ) {
|
if ( isset( $unsavedPositions[$masterName] ) ) {
|
||||||
$lb->waitForAll( $unsavedPositions[$masterName] );
|
$lb->waitForAll( $unsavedPositions[$masterName] );
|
||||||
|
|
@ -660,50 +600,38 @@ abstract class LBFactory implements DestructibleService {
|
||||||
*/
|
*/
|
||||||
final protected function baseLoadBalancerParams() {
|
final protected function baseLoadBalancerParams() {
|
||||||
return [
|
return [
|
||||||
'localDomain' => wfWikiID(),
|
'localDomain' => $this->domain,
|
||||||
'readOnlyReason' => $this->readOnlyReason,
|
'readOnlyReason' => $this->readOnlyReason,
|
||||||
'srvCache' => $this->srvCache,
|
'srvCache' => $this->srvCache,
|
||||||
'memCache' => $this->memCache,
|
|
||||||
'wanCache' => $this->wanCache,
|
'wanCache' => $this->wanCache,
|
||||||
'trxProfiler' => $this->trxProfiler,
|
'trxProfiler' => $this->trxProfiler,
|
||||||
'queryLogger' => LoggerFactory::getInstance( 'DBQuery' ),
|
'queryLogger' => $this->queryLogger,
|
||||||
'connLogger' => LoggerFactory::getInstance( 'DBConnection' ),
|
'connLogger' => $this->connLogger,
|
||||||
'replLogger' => LoggerFactory::getInstance( 'DBReplication' ),
|
'replLogger' => $this->replLogger,
|
||||||
'errorLogger' => [ MWExceptionHandler::class, 'logException' ],
|
'errorLogger' => $this->errorLogger,
|
||||||
'hostname' => wfHostname()
|
'hostname' => $this->hostname
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param LoadBalancer $lb
|
* @param ILoadBalancer $lb
|
||||||
*/
|
*/
|
||||||
protected function initLoadBalancer( LoadBalancer $lb ) {
|
protected function initLoadBalancer( ILoadBalancer $lb ) {
|
||||||
if ( $this->trxRoundId !== false ) {
|
if ( $this->trxRoundId !== false ) {
|
||||||
$lb->beginMasterChanges( $this->trxRoundId ); // set DBO_TRX
|
$lb->beginMasterChanges( $this->trxRoundId ); // set DBO_TRX
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Append ?cpPosTime parameter to a URL for ChronologyProtector purposes if needed
|
* Define a new local domain (for testing)
|
||||||
*
|
*
|
||||||
* Note that unlike cookies, this works accross domains
|
* Caller should make sure no local connection are open to the old local domain
|
||||||
*
|
*
|
||||||
* @param string $url
|
* @param string $domain
|
||||||
* @param float $time UNIX timestamp just before shutdown() was called
|
|
||||||
* @return string
|
|
||||||
* @since 1.28
|
* @since 1.28
|
||||||
*/
|
*/
|
||||||
public function appendPreShutdownTimeAsQuery( $url, $time ) {
|
public function setDomainPrefix( $domain ) {
|
||||||
$usedCluster = 0;
|
$this->domain = $domain;
|
||||||
$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 ] );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -28,11 +28,11 @@ class LoadMonitorNull implements LoadMonitor {
|
||||||
public function setLogger( LoggerInterface $logger ) {
|
public function setLogger( LoggerInterface $logger ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function scaleLoads( &$loads, $group = false, $wiki = false ) {
|
public function scaleLoads( &$loads, $group = false, $domain = false ) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getLagTimes( $serverIndexes, $wiki ) {
|
public function getLagTimes( $serverIndexes, $domain ) {
|
||||||
return array_fill_keys( $serverIndexes, 0 );
|
return array_fill_keys( $serverIndexes, 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1091,7 +1091,7 @@ abstract class Maintenance {
|
||||||
$wgLBFactoryConf['serverTemplate']['user'] = $wgDBuser;
|
$wgLBFactoryConf['serverTemplate']['user'] = $wgDBuser;
|
||||||
$wgLBFactoryConf['serverTemplate']['password'] = $wgDBpassword;
|
$wgLBFactoryConf['serverTemplate']['password'] = $wgDBpassword;
|
||||||
}
|
}
|
||||||
LBFactory::destroyInstance();
|
MediaWikiServices::getInstance()->getDBLoadBalancerFactory()->destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Per-script profiling; useful for debugging
|
// Per-script profiling; useful for debugging
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ class LBFactoryTest extends MediaWikiTestCase {
|
||||||
];
|
];
|
||||||
|
|
||||||
$this->hideDeprecated( '$wgLBFactoryConf must be updated. See RELEASE-NOTES for details' );
|
$this->hideDeprecated( '$wgLBFactoryConf must be updated. See RELEASE-NOTES for details' );
|
||||||
$result = LBFactory::getLBFactoryClass( $config );
|
$result = LBFactoryMW::getLBFactoryClass( $config );
|
||||||
|
|
||||||
$this->assertEquals( $expected, $result );
|
$this->assertEquals( $expected, $result );
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue