From 399adec9adaecc140f36b0efcd0a23af7dbdf6be Mon Sep 17 00:00:00 2001 From: Kunal Mehta Date: Mon, 29 May 2017 17:10:16 -0700 Subject: [PATCH] Turn ParserCache into a service, deprecate $parserMemc ParserCache is already a singleton, making it a good candidate for a service. $parserMemc is an odd global (it lacks the "wg" prefix) and is ripe for deprecation. The following are now deprecated: * $parserMemc global * ParserCache::singleton() * wfGetParserCacheStorage() A ParserCache::getCacheStorage() method was added for cases where direct access to the underlying BagOStuff object is necessary. Usage of $parserMemc will emit deprecation warnings through the DeprecatedGlobal class mechanism. All usage in core was migrated. Also take this opportunity to inject the $wgCacheEpoch global value into ParserCache. This will require an update to the FlaggedRevs extension. Change-Id: I2ac7afff0d8522214329248c3d1cdccd0f72bbd4 --- RELEASE-NOTES-1.30 | 4 ++ includes/GlobalFunctions.php | 1 + includes/MediaWikiServices.php | 9 ++++ includes/ServiceWiring.php | 13 +++++- includes/Setup.php | 9 +++- includes/parser/ParserCache.php | 44 ++++++++++++------- maintenance/purgeParserCache.php | 4 +- .../includes/MediaWikiServicesTest.php | 1 + .../phpunit/suites/UploadFromUrlTestSuite.php | 1 - 9 files changed, 66 insertions(+), 20 deletions(-) diff --git a/RELEASE-NOTES-1.30 b/RELEASE-NOTES-1.30 index c95e79906d..7ceb327859 100644 --- a/RELEASE-NOTES-1.30 +++ b/RELEASE-NOTES-1.30 @@ -129,6 +129,10 @@ changes to languages because of Phabricator reports. * Article::viewRedirect() is deprecated. * DeprecatedGlobal no longer supports passing in a direct value, it requires a callable factory function or a class name. +* The $parserMemc global, wfGetParserCacheStorage(), and ParserCache::singleton() + are all deprecated. The main ParserCache instance should be obtained from + MediaWikiServices instead. Access to the underlying BagOStuff is possible + through the new ParserCache::getCacheStorage() method. == Compatibility == MediaWiki 1.30 requires PHP 5.5.9 or later. There is experimental support for diff --git a/includes/GlobalFunctions.php b/includes/GlobalFunctions.php index 089ed81d78..92cb8d8569 100644 --- a/includes/GlobalFunctions.php +++ b/includes/GlobalFunctions.php @@ -3461,6 +3461,7 @@ function wfGetMessageCacheStorage() { /** * Get the cache object used by the parser cache * + * @deprecated since 1.30, use MediaWikiServices::getParserCache()->getCacheStorage() * @return BagOStuff */ function wfGetParserCacheStorage() { diff --git a/includes/MediaWikiServices.php b/includes/MediaWikiServices.php index 6161ee7355..ea0ec15c9d 100644 --- a/includes/MediaWikiServices.php +++ b/includes/MediaWikiServices.php @@ -23,6 +23,7 @@ use MWException; use MimeAnalyzer; use ObjectCache; use Parser; +use ParserCache; use ProxyLookup; use SearchEngine; use SearchEngineConfig; @@ -573,6 +574,14 @@ class MediaWikiServices extends ServiceContainer { return $this->getService( 'Parser' ); } + /** + * @since 1.30 + * @return ParserCache + */ + public function getParserCache() { + return $this->getService( 'ParserCache' ); + } + /** * @since 1.28 * @return GenderCache diff --git a/includes/ServiceWiring.php b/includes/ServiceWiring.php index 2dfcc42b26..e1244e7590 100644 --- a/includes/ServiceWiring.php +++ b/includes/ServiceWiring.php @@ -287,7 +287,18 @@ return [ return ObjectFactory::constructClassInstance( $conf['class'], [ $conf ] ); }, - 'LinkCache' => function ( MediaWikiServices $services ) { + 'ParserCache' => function( MediaWikiServices $services ) { + $config = $services->getMainConfig(); + $cache = ObjectCache::getInstance( $config->get( 'ParserCacheType' ) ); + wfDebugLog( 'caches', 'parser: ' . get_class( $cache ) ); + + return new ParserCache( + $cache, + $config->get( 'CacheEpoch' ) + ); + }, + + 'LinkCache' => function( MediaWikiServices $services ) { return new LinkCache( $services->getTitleFormatter(), $services->getMainWANObjectCache() diff --git a/includes/Setup.php b/includes/Setup.php index 579551770e..ac00fab741 100644 --- a/includes/Setup.php +++ b/includes/Setup.php @@ -683,14 +683,19 @@ $ps_memcached = Profiler::instance()->scopedProfileIn( $fname . '-memcached' ); $wgMemc = wfGetMainCache(); $messageMemc = wfGetMessageCacheStorage(); -$parserMemc = wfGetParserCacheStorage(); + +/** + * @deprecated since 1.30 + */ +$parserMemc = new DeprecatedGlobal( 'parserMemc', function() { + return MediaWikiServices::getInstance()->getParserCache()->getCacheStorage(); +}, '1.30' ); wfDebugLog( 'caches', 'cluster: ' . get_class( $wgMemc ) . ', WAN: ' . ( $wgMainWANCache === CACHE_NONE ? 'CACHE_NONE' : $wgMainWANCache ) . ', stash: ' . $wgMainStash . ', message: ' . get_class( $messageMemc ) . - ', parser: ' . get_class( $parserMemc ) . ', session: ' . get_class( ObjectCache::getInstance( $wgSessionCacheType ) ) ); diff --git a/includes/parser/ParserCache.php b/includes/parser/ParserCache.php index 3b84c4b077..c680129934 100644 --- a/includes/parser/ParserCache.php +++ b/includes/parser/ParserCache.php @@ -21,6 +21,8 @@ * @ingroup Cache Parser */ +use MediaWiki\MediaWikiServices; + /** * @ingroup Cache Parser * @todo document @@ -48,18 +50,21 @@ class ParserCache { /** @var BagOStuff */ private $mMemc; + + /** + * Anything cached prior to this is invalidated + * + * @var string + */ + private $cacheEpoch; /** * Get an instance of this object * + * @deprecated since 1.30, use MediaWikiServices instead * @return ParserCache */ public static function singleton() { - static $instance; - if ( !isset( $instance ) ) { - global $parserMemc; - $instance = new ParserCache( $parserMemc ); - } - return $instance; + return MediaWikiServices::getInstance()->getParserCache(); } /** @@ -68,11 +73,13 @@ class ParserCache { * This class use an invalidation strategy that is compatible with * MultiWriteBagOStuff in async replication mode. * - * @param BagOStuff $memCached + * @param BagOStuff $cache + * @param string $cacheEpoch Anything before this timestamp is invalidated * @throws MWException */ - protected function __construct( BagOStuff $memCached ) { - $this->mMemc = $memCached; + public function __construct( BagOStuff $cache, $cacheEpoch = '20030516000000' ) { + $this->mMemc = $cache; + $this->cacheEpoch = $cacheEpoch; } /** @@ -159,8 +166,6 @@ class ParserCache { * @since 1.30 Changed $useOutdated to an int and added the non-boolean values */ public function getKey( $article, $popts, $useOutdated = self::USE_ANYTHING ) { - global $wgCacheEpoch; - if ( is_bool( $useOutdated ) ) { $useOutdated = $useOutdated ? self::USE_ANYTHING : self::USE_CURRENT_ONLY; } @@ -180,7 +185,7 @@ class ParserCache { $cacheTime = $optionsKey->getCacheTime(); wfDebugLog( "ParserCache", "Parser options key expired, touched " . $article->getTouched() - . ", epoch $wgCacheEpoch, cached $cacheTime\n" ); + . ", epoch {$this->cacheEpoch}, cached $cacheTime\n" ); return false; } elseif ( $useOutdated < self::USE_OUTDATED && $optionsKey->isDifferentRevision( $article->getLatest() ) @@ -221,8 +226,6 @@ class ParserCache { * @return ParserOutput|bool False on failure */ public function get( $article, $popts, $useOutdated = false ) { - global $wgCacheEpoch; - $canCache = $article->checkTouched(); if ( !$canCache ) { // It's a redirect now @@ -264,7 +267,7 @@ class ParserCache { $cacheTime = $value->getCacheTime(); wfDebugLog( "ParserCache", "ParserOutput key expired, touched $touched, " - . "epoch $wgCacheEpoch, cached $cacheTime\n" ); + . "epoch {$this->cacheEpoch}, cached $cacheTime\n" ); $value = false; } elseif ( !$useOutdated && $value->isDifferentRevision( $article->getLatest() ) ) { wfIncrStats( "pcache.miss.revid" ); @@ -342,4 +345,15 @@ class ParserCache { wfDebug( "Parser output was marked as uncacheable and has not been saved.\n" ); } } + + /** + * Get the backend BagOStuff instance that + * powers the parser cache + * + * @since 1.30 + * @return BagOStuff + */ + public function getCacheStorage() { + return $this->mMemc; + } } diff --git a/maintenance/purgeParserCache.php b/maintenance/purgeParserCache.php index e00a55d29e..da2d850e15 100644 --- a/maintenance/purgeParserCache.php +++ b/maintenance/purgeParserCache.php @@ -24,6 +24,8 @@ require __DIR__ . '/Maintenance.php'; +use MediaWiki\MediaWikiServices; + /** * Maintenance script to remove old objects from the parser cache. * @@ -67,7 +69,7 @@ class PurgeParserCache extends Maintenance { $this->output( "Deleting objects expiring before " . $english->timeanddate( $date ) . "\n" ); - $pc = wfGetParserCacheStorage(); + $pc = MediaWikiServices::getInstance()->getParserCache()->getCacheStorage(); $success = $pc->deleteObjectsExpiringBefore( $date, [ $this, 'showProgressAndWait' ] ); if ( !$success ) { $this->error( "\nCannot purge this kind of parser cache.", 1 ); diff --git a/tests/phpunit/includes/MediaWikiServicesTest.php b/tests/phpunit/includes/MediaWikiServicesTest.php index b4e9626904..4e1625837e 100644 --- a/tests/phpunit/includes/MediaWikiServicesTest.php +++ b/tests/phpunit/includes/MediaWikiServicesTest.php @@ -317,6 +317,7 @@ class MediaWikiServicesTest extends MediaWikiTestCase { 'CryptHKDF' => [ 'CryptHKDF', CryptHKDF::class ], 'MediaHandlerFactory' => [ 'MediaHandlerFactory', MediaHandlerFactory::class ], 'Parser' => [ 'Parser', Parser::class ], + 'ParserCache' => [ 'ParserCache', ParserCache::class ], 'GenderCache' => [ 'GenderCache', GenderCache::class ], 'LinkCache' => [ 'LinkCache', LinkCache::class ], 'LinkRenderer' => [ 'LinkRenderer', LinkRenderer::class ], diff --git a/tests/phpunit/suites/UploadFromUrlTestSuite.php b/tests/phpunit/suites/UploadFromUrlTestSuite.php index 8366369579..f2e6858abe 100644 --- a/tests/phpunit/suites/UploadFromUrlTestSuite.php +++ b/tests/phpunit/suites/UploadFromUrlTestSuite.php @@ -61,7 +61,6 @@ class UploadFromUrlTestSuite extends PHPUnit_Framework_TestSuite { DeferredUpdates::clearPendingUpdates(); $wgMemc = wfGetMainCache(); $messageMemc = wfGetMessageCacheStorage(); - $parserMemc = wfGetParserCacheStorage(); RequestContext::resetMain(); $context = RequestContext::getMain(); -- 2.20.1