Create ParserCacheFactory.
* Makes ParserCache take the root of the key as a constructor argument * Introduces a ParserCacheFactory Next steps: - convert FlaggedRevs to using this. - cleanup This assumes that we wouldn't want to differentiate the parser cache settings per use-case, as it is now for default vs flaggedrevs caches. There are only two settings: $wgParserCacheType - name of the BagOStuff to use $wgParserCacheExpireTime - the expiration time. I think if we wanted to have different settings for different caches, we could add that as a next step. Bug: T263583 Change-Id: I188772da541a95c95a5ecece7c7dd748395506c2
This commit is contained in:
parent
b21adfc7f8
commit
fec48eb5a4
7 changed files with 163 additions and 11 deletions
|
|
@ -1103,6 +1103,7 @@ $wgAutoloadLocalClasses = [
|
|||
'MediaWiki\\Languages\\LanguageNameUtils' => __DIR__ . '/includes/language/LanguageNameUtils.php',
|
||||
'MediaWiki\\Mail\\Emailer' => __DIR__ . '/includes/mail/Emailer.php',
|
||||
'MediaWiki\\Mail\\IEmailer' => __DIR__ . '/includes/mail/IEmailer.php',
|
||||
'MediaWiki\\Parser\\ParserCacheFactory' => __DIR__ . '/includes/parser/ParserCacheFactory.php',
|
||||
'MediaWiki\\ProcOpenError' => __DIR__ . '/includes/exception/ProcOpenError.php',
|
||||
'MediaWiki\\ShellDisabledError' => __DIR__ . '/includes/exception/ShellDisabledError.php',
|
||||
'MediaWiki\\Skins\\Hook\\SkinAfterPortletHook' => __DIR__ . '/includes/skins/Hook/SkinAfterPortletHook.php',
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ use MediaWiki\Page\ContentModelChangeFactory;
|
|||
use MediaWiki\Page\MergeHistoryFactory;
|
||||
use MediaWiki\Page\MovePageFactory;
|
||||
use MediaWiki\Page\WikiPageFactory;
|
||||
use MediaWiki\Parser\ParserCacheFactory;
|
||||
use MediaWiki\Permissions\PermissionManager;
|
||||
use MediaWiki\Preferences\PreferencesFactory;
|
||||
use MediaWiki\Revision\ContributionsLookup;
|
||||
|
|
@ -1038,6 +1039,14 @@ class MediaWikiServices extends ServiceContainer {
|
|||
return $this->getService( 'ParserCache' );
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 1.36
|
||||
* @return ParserCacheFactory
|
||||
*/
|
||||
public function getParserCacheFactory() : ParserCacheFactory {
|
||||
return $this->getService( 'ParserCacheFactory' );
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 1.32
|
||||
* @return ParserFactory
|
||||
|
|
|
|||
|
|
@ -86,6 +86,7 @@ use MediaWiki\Page\MergeHistoryFactory;
|
|||
use MediaWiki\Page\MovePageFactory;
|
||||
use MediaWiki\Page\PageCommandFactory;
|
||||
use MediaWiki\Page\WikiPageFactory;
|
||||
use MediaWiki\Parser\ParserCacheFactory;
|
||||
use MediaWiki\Permissions\PermissionManager;
|
||||
use MediaWiki\Preferences\DefaultPreferencesFactory;
|
||||
use MediaWiki\Preferences\PreferencesFactory;
|
||||
|
|
@ -866,15 +867,19 @@ return [
|
|||
},
|
||||
|
||||
'ParserCache' => function ( MediaWikiServices $services ) : ParserCache {
|
||||
return $services->getParserCacheFactory()
|
||||
->getInstance( ParserCacheFactory::DEFAULT_NAME );
|
||||
},
|
||||
|
||||
'ParserCacheFactory' => function ( MediaWikiServices $services ) : ParserCacheFactory {
|
||||
$config = $services->getMainConfig();
|
||||
$cache = ObjectCache::getInstance( $config->get( 'ParserCacheType' ) );
|
||||
wfDebugLog( 'caches', 'parser: ' . get_class( $cache ) );
|
||||
|
||||
return new ParserCache(
|
||||
return new ParserCacheFactory(
|
||||
$cache,
|
||||
$config->get( 'CacheEpoch' ),
|
||||
$services->getHookContainer(),
|
||||
$services->getStatsdDataFactory()
|
||||
$services->getStatsdDataFactory(),
|
||||
LoggerFactory::getInstance( 'ParserCache' )
|
||||
);
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -50,6 +50,9 @@ class ParserCache {
|
|||
*/
|
||||
private const USE_ANYTHING = 3;
|
||||
|
||||
/** @var string The name of this ParserCache. Used as a root of the cache key. */
|
||||
private $name;
|
||||
|
||||
/** @var BagOStuff */
|
||||
private $cache;
|
||||
|
||||
|
|
@ -87,21 +90,25 @@ class ParserCache {
|
|||
* @param string $cacheEpoch Anything before this timestamp is invalidated
|
||||
* @param HookContainer $hookContainer
|
||||
* @param IBufferingStatsdDataFactory|null $stats
|
||||
* @throws MWException
|
||||
* @param string $name
|
||||
* TODO: $name: drop fallback and move to the first position once FlaggedRevs is migrated
|
||||
*/
|
||||
public function __construct(
|
||||
BagOStuff $cache,
|
||||
$cacheEpoch,
|
||||
string $cacheEpoch,
|
||||
HookContainer $hookContainer,
|
||||
IBufferingStatsdDataFactory $stats = null
|
||||
IBufferingStatsdDataFactory $stats = null,
|
||||
string $name = 'pcache'
|
||||
) {
|
||||
$this->cache = $cache;
|
||||
$this->cacheEpoch = $cacheEpoch;
|
||||
$this->hookRunner = new HookRunner( $hookContainer );
|
||||
$this->stats = $stats ?: MediaWikiServices::getInstance()->getStatsdDataFactory();
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: make private once FlaggedRevs is migrated to ParserCacheFactory
|
||||
* @param WikiPage $wikiPage
|
||||
* @param string $hash
|
||||
* @return mixed|string
|
||||
|
|
@ -113,16 +120,17 @@ class ParserCache {
|
|||
$pageid = $wikiPage->getId();
|
||||
$renderkey = (int)( $wgRequest->getVal( 'action' ) == 'render' );
|
||||
|
||||
$key = $this->cache->makeKey( 'pcache', 'idhash', "{$pageid}-{$renderkey}!{$hash}" );
|
||||
$key = $this->cache->makeKey( $this->name, 'idhash', "{$pageid}-{$renderkey}!{$hash}" );
|
||||
return $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: make private once FlaggedRevs is migrated to ParserCacheFactory
|
||||
* @param WikiPage $wikiPage
|
||||
* @return mixed|string
|
||||
*/
|
||||
protected function getOptionsKey( WikiPage $wikiPage ) {
|
||||
return $this->cache->makeKey( 'pcache', 'idoptions', $wikiPage->getId() );
|
||||
return $this->cache->makeKey( $this->name, 'idoptions', $wikiPage->getId() );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -177,7 +185,7 @@ class ParserCache {
|
|||
private function incrementStats( WikiPage $wikiPage, $metricSuffix ) {
|
||||
$contentModel = str_replace( '.', '_', $wikiPage->getContentModel() );
|
||||
$metricSuffix = str_replace( '.', '_', $metricSuffix );
|
||||
$this->stats->increment( 'pcache.' . $contentModel . '.' . $metricSuffix );
|
||||
$this->stats->increment( "{$this->name}.{$contentModel}.{$metricSuffix}" );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
97
includes/parser/ParserCacheFactory.php
Normal file
97
includes/parser/ParserCacheFactory.php
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
<?php
|
||||
/**
|
||||
* 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 Cache Parser
|
||||
*/
|
||||
|
||||
namespace MediaWiki\Parser;
|
||||
|
||||
use BagOStuff;
|
||||
use IBufferingStatsdDataFactory;
|
||||
use MediaWiki\HookContainer\HookContainer;
|
||||
use ParserCache;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
* Returns an instance of the ParserCache by its name.
|
||||
* @since 1.36
|
||||
* @package MediaWiki\Parser
|
||||
*/
|
||||
class ParserCacheFactory {
|
||||
|
||||
/** @var string name of ParserCache for the default parser */
|
||||
public const DEFAULT_NAME = 'pcache';
|
||||
|
||||
/** @var BagOStuff */
|
||||
private $cacheBackend;
|
||||
|
||||
/** @var string */
|
||||
private $cacheEpoch;
|
||||
|
||||
/** @var HookContainer */
|
||||
private $hookContainer;
|
||||
|
||||
/** @var IBufferingStatsdDataFactory */
|
||||
private $stats;
|
||||
|
||||
/** @var LoggerInterface */
|
||||
private $logger;
|
||||
|
||||
/** @var array */
|
||||
private $instanceCache = [];
|
||||
|
||||
/**
|
||||
* @param BagOStuff $cacheBackend
|
||||
* @param string $cacheEpoch
|
||||
* @param HookContainer $hookContainer
|
||||
* @param IBufferingStatsdDataFactory $stats
|
||||
* @param LoggerInterface $logger
|
||||
*/
|
||||
public function __construct(
|
||||
BagOStuff $cacheBackend,
|
||||
string $cacheEpoch,
|
||||
HookContainer $hookContainer,
|
||||
IBufferingStatsdDataFactory $stats,
|
||||
LoggerInterface $logger
|
||||
) {
|
||||
$this->cacheBackend = $cacheBackend;
|
||||
$this->cacheEpoch = $cacheEpoch;
|
||||
$this->hookContainer = $hookContainer;
|
||||
$this->stats = $stats;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a ParserCache instance by $name.
|
||||
* @param string $name
|
||||
* @return ParserCache
|
||||
*/
|
||||
public function getInstance( string $name ) : ParserCache {
|
||||
if ( !isset( $this->instanceCache[$name] ) ) {
|
||||
$this->logger->debug( "Creating ParserCache instance for {$name}" );
|
||||
$this->instanceCache[$name] = new ParserCache(
|
||||
$this->cacheBackend,
|
||||
$this->cacheEpoch,
|
||||
$this->hookContainer,
|
||||
$this->stats,
|
||||
$name
|
||||
);
|
||||
}
|
||||
return $this->instanceCache[$name];
|
||||
}
|
||||
}
|
||||
|
|
@ -92,7 +92,7 @@ trait FactoryArgTestTrait {
|
|||
$pos = $param->getPosition();
|
||||
|
||||
$type = $param->getType();
|
||||
if ( !$type ) {
|
||||
if ( !$type || $type->getName() === 'string' ) {
|
||||
// Optimistically assume a string is okay
|
||||
return "some unlikely string $pos";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
use MediaWiki\Parser\ParserCacheFactory;
|
||||
|
||||
/**
|
||||
* @covers \MediaWiki\Parser\ParserCacheFactory
|
||||
*/
|
||||
class ParserCacheFactoryTest extends MediaWikiUnitTestCase {
|
||||
use FactoryArgTestTrait;
|
||||
|
||||
protected static function getFactoryClass() {
|
||||
return ParserCacheFactory::class;
|
||||
}
|
||||
|
||||
protected static function getInstanceClass() {
|
||||
return ParserCache::class;
|
||||
}
|
||||
|
||||
protected static function getFactoryMethodName() {
|
||||
return 'getInstance';
|
||||
}
|
||||
|
||||
protected static function getExtraClassArgCount() {
|
||||
// +1 $name
|
||||
// -1 $logger
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected function getIgnoredParamNames() {
|
||||
return [ 'hookContainer', 'logger' ];
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue