Convert ParserOutputAccess to PageRecord.
Still needs to downcast to WikiPage in 2 places: 1. To check get a ContentHandler and check if content model is cacheable. We probably should just make all content models cacheable. 2. To call WikiPage::triggerOpportunisticLinksUpdate. I have an elaborate plan for this one, but it will be done separately. Change-Id: Ifd9ab0155dc1fad0c1608dafea05d16292afd057
This commit is contained in:
parent
3a047b749b
commit
cd66d7c335
5 changed files with 66 additions and 28 deletions
|
|
@ -1020,10 +1020,13 @@ return [
|
||||||
return new ParserOutputAccess(
|
return new ParserOutputAccess(
|
||||||
$services->getParserCache(),
|
$services->getParserCache(),
|
||||||
$services->getParserCacheFactory()->getRevisionOutputCache( 'rcache' ),
|
$services->getParserCacheFactory()->getRevisionOutputCache( 'rcache' ),
|
||||||
|
$services->getRevisionLookup(),
|
||||||
$services->getRevisionRenderer(),
|
$services->getRevisionRenderer(),
|
||||||
$services->getStatsdDataFactory(),
|
$services->getStatsdDataFactory(),
|
||||||
$services->getDBLoadBalancerFactory(),
|
$services->getDBLoadBalancerFactory(),
|
||||||
LoggerFactory::getProvider()
|
LoggerFactory::getProvider(),
|
||||||
|
$services->getWikiPageFactory(),
|
||||||
|
$services->getTitleFormatter()
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ use IBufferingStatsdDataFactory;
|
||||||
use InvalidArgumentException;
|
use InvalidArgumentException;
|
||||||
use MediaWiki\Logger\Spi as LoggerSpi;
|
use MediaWiki\Logger\Spi as LoggerSpi;
|
||||||
use MediaWiki\Parser\RevisionOutputCache;
|
use MediaWiki\Parser\RevisionOutputCache;
|
||||||
|
use MediaWiki\Revision\RevisionLookup;
|
||||||
use MediaWiki\Revision\RevisionRecord;
|
use MediaWiki\Revision\RevisionRecord;
|
||||||
use MediaWiki\Revision\RevisionRenderer;
|
use MediaWiki\Revision\RevisionRenderer;
|
||||||
use ParserCache;
|
use ParserCache;
|
||||||
|
|
@ -34,8 +35,8 @@ use PoolWorkArticleView;
|
||||||
use PoolWorkArticleViewCurrent;
|
use PoolWorkArticleViewCurrent;
|
||||||
use PoolWorkArticleViewOld;
|
use PoolWorkArticleViewOld;
|
||||||
use Status;
|
use Status;
|
||||||
|
use TitleFormatter;
|
||||||
use Wikimedia\Rdbms\ILBFactory;
|
use Wikimedia\Rdbms\ILBFactory;
|
||||||
use WikiPage;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service for getting rendered output of a given page.
|
* Service for getting rendered output of a given page.
|
||||||
|
|
@ -92,6 +93,9 @@ class ParserOutputAccess {
|
||||||
*/
|
*/
|
||||||
private $secondaryCache;
|
private $secondaryCache;
|
||||||
|
|
||||||
|
/** @var RevisionLookup */
|
||||||
|
private $revisionLookup;
|
||||||
|
|
||||||
/** @var RevisionRenderer */
|
/** @var RevisionRenderer */
|
||||||
private $revisionRenderer;
|
private $revisionRenderer;
|
||||||
|
|
||||||
|
|
@ -104,41 +108,56 @@ class ParserOutputAccess {
|
||||||
/** @var LoggerSpi */
|
/** @var LoggerSpi */
|
||||||
private $loggerSpi;
|
private $loggerSpi;
|
||||||
|
|
||||||
|
/** @var WikiPageFactory */
|
||||||
|
private $wikiPageFactory;
|
||||||
|
|
||||||
|
/** @var TitleFormatter */
|
||||||
|
private $titleFormatter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param ParserCache $primaryCache
|
* @param ParserCache $primaryCache
|
||||||
* @param RevisionOutputCache $secondaryCache
|
* @param RevisionOutputCache $secondaryCache
|
||||||
|
* @param RevisionLookup $revisionLookup
|
||||||
* @param RevisionRenderer $revisionRenderer
|
* @param RevisionRenderer $revisionRenderer
|
||||||
* @param IBufferingStatsdDataFactory $statsDataFactory
|
* @param IBufferingStatsdDataFactory $statsDataFactory
|
||||||
* @param ILBFactory $lbFactory
|
* @param ILBFactory $lbFactory
|
||||||
* @param LoggerSpi $loggerSpi
|
* @param LoggerSpi $loggerSpi
|
||||||
|
* @param WikiPageFactory $wikiPageFactory
|
||||||
|
* @param TitleFormatter $titleFormatter
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
ParserCache $primaryCache,
|
ParserCache $primaryCache,
|
||||||
RevisionOutputCache $secondaryCache,
|
RevisionOutputCache $secondaryCache,
|
||||||
|
RevisionLookup $revisionLookup,
|
||||||
RevisionRenderer $revisionRenderer,
|
RevisionRenderer $revisionRenderer,
|
||||||
IBufferingStatsdDataFactory $statsDataFactory,
|
IBufferingStatsdDataFactory $statsDataFactory,
|
||||||
ILBFactory $lbFactory,
|
ILBFactory $lbFactory,
|
||||||
LoggerSpi $loggerSpi
|
LoggerSpi $loggerSpi,
|
||||||
|
WikiPageFactory $wikiPageFactory,
|
||||||
|
TitleFormatter $titleFormatter
|
||||||
) {
|
) {
|
||||||
$this->primaryCache = $primaryCache;
|
$this->primaryCache = $primaryCache;
|
||||||
$this->secondaryCache = $secondaryCache;
|
$this->secondaryCache = $secondaryCache;
|
||||||
|
$this->revisionLookup = $revisionLookup;
|
||||||
$this->revisionRenderer = $revisionRenderer;
|
$this->revisionRenderer = $revisionRenderer;
|
||||||
$this->statsDataFactory = $statsDataFactory;
|
$this->statsDataFactory = $statsDataFactory;
|
||||||
$this->lbFactory = $lbFactory;
|
$this->lbFactory = $lbFactory;
|
||||||
$this->loggerSpi = $loggerSpi;
|
$this->loggerSpi = $loggerSpi;
|
||||||
|
$this->wikiPageFactory = $wikiPageFactory;
|
||||||
|
$this->titleFormatter = $titleFormatter;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use a cache?
|
* Use a cache?
|
||||||
*
|
*
|
||||||
* @param WikiPage $page
|
* @param PageRecord $page
|
||||||
* @param ParserOptions $parserOptions ParserOptions to check
|
* @param ParserOptions $parserOptions ParserOptions to check
|
||||||
* @param RevisionRecord|null $rev
|
* @param RevisionRecord|null $rev
|
||||||
*
|
*
|
||||||
* @return string One of the CACHE_XXX constants.
|
* @return string One of the CACHE_XXX constants.
|
||||||
*/
|
*/
|
||||||
private function shouldUseCache(
|
private function shouldUseCache(
|
||||||
WikiPage $page,
|
PageRecord $page,
|
||||||
ParserOptions $parserOptions,
|
ParserOptions $parserOptions,
|
||||||
?RevisionRecord $rev
|
?RevisionRecord $rev
|
||||||
) {
|
) {
|
||||||
|
|
@ -151,11 +170,12 @@ class ParserOutputAccess {
|
||||||
// NOTE: when we allow caching of old revisions in the future,
|
// NOTE: when we allow caching of old revisions in the future,
|
||||||
// we must not allow caching of deleted revisions.
|
// we must not allow caching of deleted revisions.
|
||||||
|
|
||||||
if ( !$page->exists() || !$page->getContentHandler()->isParserCacheSupported() ) {
|
$wikiPage = $this->wikiPageFactory->newFromTitle( $page );
|
||||||
|
if ( !$page->exists() || !$wikiPage->getContentHandler()->isParserCacheSupported() ) {
|
||||||
return self::CACHE_NONE;
|
return self::CACHE_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !$rev || $rev->getId() === $page->getLatest() ) {
|
if ( !$rev || $rev->getId() === $page->getLatest( PageRecord::LOCAL ) ) {
|
||||||
// current revision
|
// current revision
|
||||||
return self::CACHE_PRIMARY;
|
return self::CACHE_PRIMARY;
|
||||||
}
|
}
|
||||||
|
|
@ -171,7 +191,7 @@ class ParserOutputAccess {
|
||||||
/**
|
/**
|
||||||
* Returns the rendered output for the given page if it is present in the cache.
|
* Returns the rendered output for the given page if it is present in the cache.
|
||||||
*
|
*
|
||||||
* @param WikiPage $page
|
* @param PageRecord $page
|
||||||
* @param ParserOptions $parserOptions
|
* @param ParserOptions $parserOptions
|
||||||
* @param RevisionRecord|null $revision
|
* @param RevisionRecord|null $revision
|
||||||
* @param int $options Bitfield using the OPT_XXX constants
|
* @param int $options Bitfield using the OPT_XXX constants
|
||||||
|
|
@ -179,7 +199,7 @@ class ParserOutputAccess {
|
||||||
* @return ParserOutput|null
|
* @return ParserOutput|null
|
||||||
*/
|
*/
|
||||||
public function getCachedParserOutput(
|
public function getCachedParserOutput(
|
||||||
WikiPage $page,
|
PageRecord $page,
|
||||||
ParserOptions $parserOptions,
|
ParserOptions $parserOptions,
|
||||||
?RevisionRecord $revision = null,
|
?RevisionRecord $revision = null,
|
||||||
int $options = 0
|
int $options = 0
|
||||||
|
|
@ -204,7 +224,7 @@ class ParserOutputAccess {
|
||||||
* Returns the rendered output for the given page.
|
* Returns the rendered output for the given page.
|
||||||
* Caching and concurrency control is applied.
|
* Caching and concurrency control is applied.
|
||||||
*
|
*
|
||||||
* @param WikiPage $page
|
* @param PageRecord $page
|
||||||
* @param ParserOptions $parserOptions
|
* @param ParserOptions $parserOptions
|
||||||
* @param RevisionRecord|null $revision
|
* @param RevisionRecord|null $revision
|
||||||
* @param int $options Bitfield using the OPT_XXX constants
|
* @param int $options Bitfield using the OPT_XXX constants
|
||||||
|
|
@ -223,7 +243,7 @@ class ParserOutputAccess {
|
||||||
* - 'nopagetext' (error) The page does not exist
|
* - 'nopagetext' (error) The page does not exist
|
||||||
*/
|
*/
|
||||||
public function getParserOutput(
|
public function getParserOutput(
|
||||||
WikiPage $page,
|
PageRecord $page,
|
||||||
ParserOptions $parserOptions,
|
ParserOptions $parserOptions,
|
||||||
?RevisionRecord $revision = null,
|
?RevisionRecord $revision = null,
|
||||||
int $options = 0
|
int $options = 0
|
||||||
|
|
@ -245,7 +265,8 @@ class ParserOutputAccess {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !$revision ) {
|
if ( !$revision ) {
|
||||||
$revision = $page->getRevisionRecord();
|
$revision = $page->getLatest() ?
|
||||||
|
$this->revisionLookup->getRevisionById( $page->getLatest() ) : null;
|
||||||
|
|
||||||
if ( !$revision ) {
|
if ( !$revision ) {
|
||||||
$this->statsDataFactory->increment( "ParserOutputAccess.Status.norev" );
|
$this->statsDataFactory->increment( "ParserOutputAccess.Status.norev" );
|
||||||
|
|
@ -295,14 +316,14 @@ class ParserOutputAccess {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param WikiPage $page
|
* @param PageRecord $page
|
||||||
* @param RevisionRecord|null $revision
|
* @param RevisionRecord|null $revision
|
||||||
* @param int $options
|
* @param int $options
|
||||||
*
|
*
|
||||||
* @return Status|null
|
* @return Status|null
|
||||||
*/
|
*/
|
||||||
private function checkPreconditions(
|
private function checkPreconditions(
|
||||||
WikiPage $page,
|
PageRecord $page,
|
||||||
?RevisionRecord $revision = null,
|
?RevisionRecord $revision = null,
|
||||||
int $options = 0
|
int $options = 0
|
||||||
): ?Status {
|
): ?Status {
|
||||||
|
|
@ -330,7 +351,7 @@ class ParserOutputAccess {
|
||||||
'missing-revision-permission',
|
'missing-revision-permission',
|
||||||
$revision->getId(),
|
$revision->getId(),
|
||||||
$revision->getTimestamp(),
|
$revision->getTimestamp(),
|
||||||
$page->getTitle()->getPrefixedDBkey()
|
$this->titleFormatter->getPrefixedDBkey( $page )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -339,15 +360,15 @@ class ParserOutputAccess {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param WikiPage $page
|
* @param PageRecord $page
|
||||||
* @param ParserOptions $parserOptions
|
* @param ParserOptions $parserOptions
|
||||||
* @param RevisionRecord|null $revision
|
* @param RevisionRecord $revision
|
||||||
* @param int $options
|
* @param int $options
|
||||||
*
|
*
|
||||||
* @return PoolWorkArticleView
|
* @return PoolWorkArticleView
|
||||||
*/
|
*/
|
||||||
private function newPoolWorkArticleView(
|
private function newPoolWorkArticleView(
|
||||||
WikiPage $page,
|
PageRecord $page,
|
||||||
ParserOptions $parserOptions,
|
ParserOptions $parserOptions,
|
||||||
RevisionRecord $revision,
|
RevisionRecord $revision,
|
||||||
int $options
|
int $options
|
||||||
|
|
@ -376,7 +397,8 @@ class ParserOutputAccess {
|
||||||
$this->revisionRenderer,
|
$this->revisionRenderer,
|
||||||
$this->primaryCache,
|
$this->primaryCache,
|
||||||
$this->lbFactory,
|
$this->lbFactory,
|
||||||
$this->loggerSpi
|
$this->loggerSpi,
|
||||||
|
$this->wikiPageFactory
|
||||||
);
|
);
|
||||||
|
|
||||||
case $useCache == self::CACHE_SECONDARY:
|
case $useCache == self::CACHE_SECONDARY:
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use MediaWiki\Logger\Spi as LoggerSpi;
|
use MediaWiki\Logger\Spi as LoggerSpi;
|
||||||
|
use MediaWiki\Page\PageRecord;
|
||||||
|
use MediaWiki\Page\WikiPageFactory;
|
||||||
use MediaWiki\Revision\RevisionRecord;
|
use MediaWiki\Revision\RevisionRecord;
|
||||||
use MediaWiki\Revision\RevisionRenderer;
|
use MediaWiki\Revision\RevisionRenderer;
|
||||||
use Wikimedia\Rdbms\ILBFactory;
|
use Wikimedia\Rdbms\ILBFactory;
|
||||||
|
|
@ -33,7 +35,7 @@ class PoolWorkArticleViewCurrent extends PoolWorkArticleView {
|
||||||
/** @var string */
|
/** @var string */
|
||||||
private $workKey;
|
private $workKey;
|
||||||
|
|
||||||
/** @var WikiPage */
|
/** @var PageRecord */
|
||||||
private $page;
|
private $page;
|
||||||
|
|
||||||
/** @var ParserCache */
|
/** @var ParserCache */
|
||||||
|
|
@ -42,29 +44,34 @@ class PoolWorkArticleViewCurrent extends PoolWorkArticleView {
|
||||||
/** @var ILBFactory */
|
/** @var ILBFactory */
|
||||||
private $lbFactory;
|
private $lbFactory;
|
||||||
|
|
||||||
|
/** @var WikiPageFactory */
|
||||||
|
private $wikiPageFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $workKey
|
* @param string $workKey
|
||||||
* @param WikiPage $page
|
* @param PageRecord $page
|
||||||
* @param RevisionRecord $revision Revision to render
|
* @param RevisionRecord $revision Revision to render
|
||||||
* @param ParserOptions $parserOptions ParserOptions to use for the parse
|
* @param ParserOptions $parserOptions ParserOptions to use for the parse
|
||||||
* @param RevisionRenderer $revisionRenderer
|
* @param RevisionRenderer $revisionRenderer
|
||||||
* @param ParserCache $parserCache
|
* @param ParserCache $parserCache
|
||||||
* @param ILBFactory $lbFactory
|
* @param ILBFactory $lbFactory
|
||||||
* @param LoggerSpi $loggerSpi
|
* @param LoggerSpi $loggerSpi
|
||||||
|
* @param WikiPageFactory $wikiPageFactory
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
string $workKey,
|
string $workKey,
|
||||||
WikiPage $page,
|
PageRecord $page,
|
||||||
RevisionRecord $revision,
|
RevisionRecord $revision,
|
||||||
ParserOptions $parserOptions,
|
ParserOptions $parserOptions,
|
||||||
RevisionRenderer $revisionRenderer,
|
RevisionRenderer $revisionRenderer,
|
||||||
ParserCache $parserCache,
|
ParserCache $parserCache,
|
||||||
ILBFactory $lbFactory,
|
ILBFactory $lbFactory,
|
||||||
LoggerSpi $loggerSpi
|
LoggerSpi $loggerSpi,
|
||||||
|
WikiPageFactory $wikiPageFactory
|
||||||
) {
|
) {
|
||||||
// TODO: Remove support for partially initialized RevisionRecord instances once
|
// TODO: Remove support for partially initialized RevisionRecord instances once
|
||||||
// Article no longer uses fake revisions.
|
// Article no longer uses fake revisions.
|
||||||
if ( $revision->getPageId() && $revision->getPageId() !== $page->getTitle()->getArticleID() ) {
|
if ( $revision->getPageId() && $revision->getPageId() !== $page->getId() ) {
|
||||||
throw new InvalidArgumentException( '$page parameter mismatches $revision parameter' );
|
throw new InvalidArgumentException( '$page parameter mismatches $revision parameter' );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -74,6 +81,7 @@ class PoolWorkArticleViewCurrent extends PoolWorkArticleView {
|
||||||
$this->page = $page;
|
$this->page = $page;
|
||||||
$this->parserCache = $parserCache;
|
$this->parserCache = $parserCache;
|
||||||
$this->lbFactory = $lbFactory;
|
$this->lbFactory = $lbFactory;
|
||||||
|
$this->wikiPageFactory = $wikiPageFactory;
|
||||||
$this->cacheable = true;
|
$this->cacheable = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -95,7 +103,8 @@ class PoolWorkArticleViewCurrent extends PoolWorkArticleView {
|
||||||
* @param ParserOutput $output
|
* @param ParserOutput $output
|
||||||
*/
|
*/
|
||||||
protected function afterWork( ParserOutput $output ) {
|
protected function afterWork( ParserOutput $output ) {
|
||||||
$this->page->triggerOpportunisticLinksUpdate( $this->parserOutput );
|
$this->wikiPageFactory->newFromTitle( $this->page )
|
||||||
|
->triggerOpportunisticLinksUpdate( $this->parserOutput );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -144,10 +144,13 @@ class ParserOutputAccessTest extends MediaWikiIntegrationTestCase {
|
||||||
return new ParserOutputAccess(
|
return new ParserOutputAccess(
|
||||||
$parserCache,
|
$parserCache,
|
||||||
$revisionOutputCache,
|
$revisionOutputCache,
|
||||||
|
$this->getServiceContainer()->getRevisionLookup(),
|
||||||
$revRenderer,
|
$revRenderer,
|
||||||
$stats,
|
$stats,
|
||||||
$lbFactory,
|
$lbFactory,
|
||||||
$this->getLoggerSpi()
|
$this->getLoggerSpi(),
|
||||||
|
$this->getServiceContainer()->getWikiPageFactory(),
|
||||||
|
$this->getServiceContainer()->getTitleFormatter()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -251,7 +254,7 @@ class ParserOutputAccessTest extends MediaWikiIntegrationTestCase {
|
||||||
|
|
||||||
$revisionStore = $this->createNoOpMock(
|
$revisionStore = $this->createNoOpMock(
|
||||||
RevisionStore::class,
|
RevisionStore::class,
|
||||||
[ 'getRevisionByTitle', 'getKnownCurrentRevision' ]
|
[ 'getRevisionByTitle', 'getKnownCurrentRevision', 'getRevisionById' ]
|
||||||
);
|
);
|
||||||
$revisionStore->method( 'getRevisionById' )->willReturn( null );
|
$revisionStore->method( 'getRevisionById' )->willReturn( null );
|
||||||
$revisionStore->method( 'getRevisionByTitle' )->willReturn( null );
|
$revisionStore->method( 'getRevisionByTitle' )->willReturn( null );
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,8 @@ class PoolWorkArticleViewCurrentTest extends PoolWorkArticleViewTest {
|
||||||
$revisionRenderer,
|
$revisionRenderer,
|
||||||
$parserCache,
|
$parserCache,
|
||||||
$lbFactory,
|
$lbFactory,
|
||||||
$this->getLoggerSpi()
|
$this->getLoggerSpi(),
|
||||||
|
$this->getServiceContainer()->getWikiPageFactory()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue