diff options
author | daniel <dkinzler@wikimedia.org> | 2022-05-24 15:50:02 +0200 |
---|---|---|
committer | Amir Sarabadani <ladsgroup@gmail.com> | 2022-08-05 17:32:12 +0200 |
commit | 5b0b54599bfddd72e9884ef37e932eb26bc8dc5b (patch) | |
tree | 8c814f3645f077c069db30490c21eb4c8a08bf56 /includes/db | |
parent | 6bfbc4b6cc4cf22598ad506f6d5d9e5dec45b5cb (diff) | |
download | mediawikicore-5b0b54599bfddd72e9884ef37e932eb26bc8dc5b.tar.gz mediawikicore-5b0b54599bfddd72e9884ef37e932eb26bc8dc5b.zip |
Allow DB config to be reloaded on the fly
This introduces $wgLBFactoryConf['configCallback'] which can be set to a
function that returns updates to be applied to $wgLBFactoryConf. The new
method LBFactory::autoreConfigure() can be called to check the callabck
and, if the config changed, reconfigure all existing LoadBalancers.
Reconfiguring the LoadBalancers causes all open connections to be
invalidated; however, any DBConnRef instances will remain valid and will
acquire a fresh connection from the LoadBalancer automatically when
appropriate.
As a proof of concept, this patch adds support for config reloding
into WikiExporter.
Bug: T298485
Change-Id: I6c3ffde62f6e038730736abe980befd90ec43e1a
Diffstat (limited to 'includes/db')
-rw-r--r-- | includes/db/MWLBFactory.php | 125 |
1 files changed, 82 insertions, 43 deletions
diff --git a/includes/db/MWLBFactory.php b/includes/db/MWLBFactory.php index 7fbcd2873b06..81cea3d78e7b 100644 --- a/includes/db/MWLBFactory.php +++ b/includes/db/MWLBFactory.php @@ -38,7 +38,7 @@ use Wikimedia\RequestTimeout\CriticalSectionProvider; * @internal For use by core ServiceWiring only. * @ingroup Database */ -abstract class MWLBFactory { +class MWLBFactory { /** @var array Cache of already-logged deprecation messages */ private static $loggedDeprecations = []; @@ -67,9 +67,36 @@ abstract class MWLBFactory { MainConfigNames::SQLiteDataDir, MainConfigNames::SQLMode, ]; + /** + * @var ServiceOptions + */ + private $options; + /** + * @var ConfiguredReadOnlyMode + */ + private $readOnlyMode; + /** + * @var BagOStuff + */ + private $cpStash; + /** + * @var BagOStuff + */ + private $srvCache; + /** + * @var WANObjectCache + */ + private $wanCache; + /** + * @var CriticalSectionProvider + */ + private $csProvider; + /** + * @var StatsdDataFactoryInterface + */ + private $statsdDataFactory; /** - * @param array $lbConf Config for LBFactory::__construct() * @param ServiceOptions $options * @param ConfiguredReadOnlyMode $readOnlyMode * @param BagOStuff $cpStash @@ -77,11 +104,8 @@ abstract class MWLBFactory { * @param WANObjectCache $wanCache * @param CriticalSectionProvider $csProvider * @param StatsdDataFactoryInterface $statsdDataFactory - * @return array - * @internal For use with service wiring */ - public static function applyDefaultConfig( - array $lbConf, + public function __construct( ServiceOptions $options, ConfiguredReadOnlyMode $readOnlyMode, BagOStuff $cpStash, @@ -90,15 +114,30 @@ abstract class MWLBFactory { CriticalSectionProvider $csProvider, StatsdDataFactoryInterface $statsdDataFactory ) { - $options->assertRequiredOptions( self::APPLY_DEFAULT_CONFIG_OPTIONS ); + $this->options = $options; + $this->readOnlyMode = $readOnlyMode; + $this->cpStash = $cpStash; + $this->srvCache = $srvCache; + $this->wanCache = $wanCache; + $this->csProvider = $csProvider; + $this->statsdDataFactory = $statsdDataFactory; + } + + /** + * @param array $lbConf Config for LBFactory::__construct() + * @return array + * @internal For use with service wiring + */ + public function applyDefaultConfig( array $lbConf ) { + $this->options->assertRequiredOptions( self::APPLY_DEFAULT_CONFIG_OPTIONS ); $typesWithSchema = self::getDbTypesWithSchemas(); $lbConf += [ 'localDomain' => new DatabaseDomain( - $options->get( MainConfigNames::DBname ), - $options->get( MainConfigNames::DBmwschema ), - $options->get( MainConfigNames::DBprefix ) + $this->options->get( MainConfigNames::DBname ), + $this->options->get( MainConfigNames::DBmwschema ), + $this->options->get( MainConfigNames::DBprefix ) ), 'profiler' => static function ( $section ) { return Profiler::instance()->scopedProfileIn( $section ); @@ -110,11 +149,11 @@ abstract class MWLBFactory { 'perfLogger' => LoggerFactory::getInstance( 'DBPerformance' ), 'errorLogger' => [ MWExceptionHandler::class, 'logException' ], 'deprecationLogger' => [ static::class, 'logDeprecation' ], - 'statsdDataFactory' => $statsdDataFactory, - 'cliMode' => $options->get( 'CommandLineMode' ), - 'readOnlyReason' => $readOnlyMode->getReason(), - 'defaultGroup' => $options->get( MainConfigNames::DBDefaultGroup ), - 'criticalSectionProvider' => $csProvider + 'statsdDataFactory' => $this->statsdDataFactory, + 'cliMode' => $this->options->get( 'CommandLineMode' ), + 'readOnlyReason' => $this->readOnlyMode->getReason(), + 'defaultGroup' => $this->options->get( MainConfigNames::DBDefaultGroup ), + 'criticalSectionProvider' => $this->csProvider ]; $serversCheck = []; @@ -124,55 +163,55 @@ abstract class MWLBFactory { if ( $lbConf['class'] === Wikimedia\Rdbms\LBFactorySimple::class ) { if ( isset( $lbConf['servers'] ) ) { // Server array is already explicitly configured - } elseif ( is_array( $options->get( MainConfigNames::DBservers ) ) ) { + } elseif ( is_array( $this->options->get( MainConfigNames::DBservers ) ) ) { $lbConf['servers'] = []; - foreach ( $options->get( MainConfigNames::DBservers ) as $i => $server ) { - $lbConf['servers'][$i] = self::initServerInfo( $server, $options ); + foreach ( $this->options->get( MainConfigNames::DBservers ) as $i => $server ) { + $lbConf['servers'][$i] = self::initServerInfo( $server, $this->options ); } } else { $server = self::initServerInfo( [ - 'host' => $options->get( MainConfigNames::DBserver ), - 'user' => $options->get( MainConfigNames::DBuser ), - 'password' => $options->get( MainConfigNames::DBpassword ), - 'dbname' => $options->get( MainConfigNames::DBname ), - 'type' => $options->get( MainConfigNames::DBtype ), + 'host' => $this->options->get( MainConfigNames::DBserver ), + 'user' => $this->options->get( MainConfigNames::DBuser ), + 'password' => $this->options->get( MainConfigNames::DBpassword ), + 'dbname' => $this->options->get( MainConfigNames::DBname ), + 'type' => $this->options->get( MainConfigNames::DBtype ), 'load' => 1 ], - $options + $this->options ); - if ( $options->get( MainConfigNames::DBssl ) ) { + if ( $this->options->get( MainConfigNames::DBssl ) ) { $server['ssl'] = true; } - $server['flags'] |= $options->get( MainConfigNames::DBcompress ) ? DBO_COMPRESS : 0; + $server['flags'] |= $this->options->get( MainConfigNames::DBcompress ) ? DBO_COMPRESS : 0; $lbConf['servers'] = [ $server ]; } if ( !isset( $lbConf['externalClusters'] ) ) { - $lbConf['externalClusters'] = $options->get( MainConfigNames::ExternalServers ); + $lbConf['externalClusters'] = $this->options->get( MainConfigNames::ExternalServers ); } $serversCheck = $lbConf['servers']; } elseif ( $lbConf['class'] === Wikimedia\Rdbms\LBFactoryMulti::class ) { if ( isset( $lbConf['serverTemplate'] ) ) { if ( in_array( $lbConf['serverTemplate']['type'], $typesWithSchema, true ) ) { - $lbConf['serverTemplate']['schema'] = $options->get( MainConfigNames::DBmwschema ); + $lbConf['serverTemplate']['schema'] = $this->options->get( MainConfigNames::DBmwschema ); } - $lbConf['serverTemplate']['sqlMode'] = $options->get( MainConfigNames::SQLMode ); + $lbConf['serverTemplate']['sqlMode'] = $this->options->get( MainConfigNames::SQLMode ); $serversCheck = [ $lbConf['serverTemplate'] ]; } } self::assertValidServerConfigs( $serversCheck, - $options->get( MainConfigNames::DBname ), - $options->get( MainConfigNames::DBprefix ) + $this->options->get( MainConfigNames::DBname ), + $this->options->get( MainConfigNames::DBprefix ) ); - $lbConf['cpStash'] = $cpStash; - $lbConf['srvCache'] = $srvCache; - $lbConf['wanCache'] = $wanCache; + $lbConf['cpStash'] = $this->cpStash; + $lbConf['srvCache'] = $this->srvCache; + $lbConf['wanCache'] = $this->wanCache; return $lbConf; } @@ -180,7 +219,7 @@ abstract class MWLBFactory { /** * @return array */ - private static function getDbTypesWithSchemas() { + private function getDbTypesWithSchemas() { return [ 'postgres' ]; } @@ -189,7 +228,7 @@ abstract class MWLBFactory { * @param ServiceOptions $options * @return array */ - private static function initServerInfo( array $server, ServiceOptions $options ) { + private function initServerInfo( array $server, ServiceOptions $options ) { if ( $server['type'] === 'sqlite' ) { $httpMethod = $_SERVER['REQUEST_METHOD'] ?? null; // T93097: hint for how file-based databases (e.g. sqlite) should go about locking. @@ -238,7 +277,7 @@ abstract class MWLBFactory { * @param string $ldDB Local domain database name * @param string $ldTP Local domain prefix */ - private static function assertValidServerConfigs( array $servers, $ldDB, $ldTP ) { + private function assertValidServerConfigs( array $servers, $ldDB, $ldTP ) { foreach ( $servers as $server ) { $type = $server['type'] ?? null; $srvDB = $server['dbname'] ?? null; // server DB @@ -267,7 +306,7 @@ abstract class MWLBFactory { * @param string $dbType Database type * @return never */ - private static function reportIfPrefixSet( $prefix, $dbType ) { + private function reportIfPrefixSet( $prefix, $dbType ) { $e = new UnexpectedValueException( "\$wgDBprefix is set to '$prefix' but the database type is '$dbType'. " . "MediaWiki does not support using a table prefix with this RDBMS type." @@ -281,7 +320,7 @@ abstract class MWLBFactory { * @param string $ldDB Local DB domain database * @return never */ - private static function reportMismatchedDBs( $srvDB, $ldDB ) { + private function reportMismatchedDBs( $srvDB, $ldDB ) { $e = new UnexpectedValueException( "\$wgDBservers has dbname='$srvDB' but \$wgDBname='$ldDB'. " . "Set \$wgDBname to the database used by this wiki project. " . @@ -299,7 +338,7 @@ abstract class MWLBFactory { * @param string $ldTP Local DB domain database * @return never */ - private static function reportMismatchedPrefixes( $srvTP, $ldTP ) { + private function reportMismatchedPrefixes( $srvTP, $ldTP ) { $e = new UnexpectedValueException( "\$wgDBservers has tablePrefix='$srvTP' but \$wgDBprefix='$ldTP'. " . "Set \$wgDBprefix to the table prefix used by this wiki project. " . @@ -319,7 +358,7 @@ abstract class MWLBFactory { * @param array $config (e.g. $wgLBFactoryConf) * @return string Class name */ - public static function getLBFactoryClass( array $config ) { + public function getLBFactoryClass( array $config ) { $compat = [ // For LocalSettings.php compat after removing underscores (since 1.23). 'LBFactory_Single' => Wikimedia\Rdbms\LBFactorySingle::class, @@ -338,7 +377,7 @@ abstract class MWLBFactory { /** * @param ILBFactory $lbFactory */ - public static function setDomainAliases( ILBFactory $lbFactory ) { + public function setDomainAliases( ILBFactory $lbFactory ) { $domain = DatabaseDomain::newFromId( $lbFactory->getLocalDomainID() ); // For compatibility with hyphenated $wgDBname values on older wikis, handle callers // that assume corresponding database domain IDs and wiki IDs have identical values @@ -372,7 +411,7 @@ abstract class MWLBFactory { * @param Config $config * @param IBufferingStatsdDataFactory $stats */ - public static function applyGlobalState( + public function applyGlobalState( ILBFactory $lbFactory, Config $config, IBufferingStatsdDataFactory $stats |