MediaWiki master
PoolWorkArticleViewCurrent.php
Go to the documentation of this file.
1<?php
21namespace MediaWiki\PoolCounter;
22
23use InvalidArgumentException;
24use MediaWiki\Logger\Spi as LoggerSpi;
34use ParserCache;
38
46 private $workKey;
48 private $page;
50 private $parserCache;
52 private $lbFactory;
54 private $wikiPageFactory;
56 private bool $triggerLinksUpdate;
57 private ChronologyProtector $chronologyProtector;
58
73 public function __construct(
74 string $workKey,
75 PageRecord $page,
78 RevisionRenderer $revisionRenderer,
79 ParserCache $parserCache,
80 ILBFactory $lbFactory,
81 ChronologyProtector $chronologyProtector,
82 LoggerSpi $loggerSpi,
83 WikiPageFactory $wikiPageFactory,
84 bool $cacheable = true,
85 bool $triggerLinksUpdate = false
86 ) {
87 // TODO: Remove support for partially initialized RevisionRecord instances once
88 // Article no longer uses fake revisions.
89 if ( $revision->getPageId() && $revision->getPageId() !== $page->getId() ) {
90 throw new InvalidArgumentException( '$page parameter mismatches $revision parameter' );
91 }
92
93 parent::__construct( $workKey, $revision, $parserOptions, $revisionRenderer, $loggerSpi );
94
95 $this->workKey = $workKey;
96 $this->page = $page;
97 $this->parserCache = $parserCache;
98 $this->lbFactory = $lbFactory;
99 $this->chronologyProtector = $chronologyProtector;
100 $this->wikiPageFactory = $wikiPageFactory;
101 $this->cacheable = $cacheable;
102 $this->triggerLinksUpdate = $triggerLinksUpdate;
103 }
104
108 public function doWork() {
109 // T371713: Temporary statistics collection code to determine
110 // feasibility of Parsoid selective update
111 $sampleRate = MediaWikiServices::getInstance()->getMainConfig()->get(
113 );
114 $doSample = ( $sampleRate && mt_rand( 1, $sampleRate ) === 1 );
115
116 $previousOutput = null;
117 if ( $this->parserOptions->getUseParsoid() || $doSample ) {
118 // Parsoid can do selective updates, so it is worth checking the
119 // cache for an existing entry. Not worth it for the legacy
120 // parser, though.
121 $previousOutput = $this->parserCache->getDirty( $this->page, $this->parserOptions ) ?: null;
122 }
123 $status = $this->renderRevision( $previousOutput, $doSample, 'PoolWorkArticleViewCurrent' );
125 $output = $status->getValue();
126
127 if ( $output ) {
128 if ( $this->cacheable && $output->isCacheable() ) {
129 $this->parserCache->save(
130 $output,
131 $this->page,
132 $this->parserOptions
133 );
134 }
135
136 if ( $this->triggerLinksUpdate ) {
137 $this->wikiPageFactory->newFromTitle( $this->page )->triggerOpportunisticLinksUpdate( $output );
138 }
139 }
140
141 return $status;
142 }
143
147 public function getCachedWork() {
148 $parserOutput = $this->parserCache->get( $this->page, $this->parserOptions );
149
150 $logger = $this->loggerSpi->getLogger( 'PoolWorkArticleView' );
151 $logger->debug( $parserOutput ? 'parser cache hit' : 'parser cache miss' );
152
153 return $parserOutput ? Status::newGood( $parserOutput ) : false;
154 }
155
160 public function fallback( $fast ) {
161 $parserOutput = $this->parserCache->getDirty( $this->page, $this->parserOptions );
162
163 $logger = $this->loggerSpi->getLogger( 'dirty' );
164
165 if ( !$parserOutput ) {
166 $logger->info( 'dirty missing' );
167 return false;
168 }
169
170 if ( $fast ) {
171 /* Check if the stale response is from before the last write to the
172 * DB by this user. Declining to return a stale response in this
173 * case ensures that the user will see their own edit after page
174 * save.
175 *
176 * Note that the CP touch time is the timestamp of the shutdown of
177 * the save request, so there is a bias towards avoiding fast stale
178 * responses of potentially several seconds.
179 */
180 $lastWriteTime = $this->chronologyProtector->getTouched( $this->lbFactory->getMainLB() );
181 $cacheTime = MWTimestamp::convert( TS_UNIX, $parserOutput->getCacheTime() );
182 if ( $lastWriteTime && $cacheTime <= $lastWriteTime ) {
183 $logger->info(
184 'declining to send dirty output since cache time ' .
185 '{cacheTime} is before last write time {lastWriteTime}',
186 [
187 'workKey' => $this->workKey,
188 'cacheTime' => $cacheTime,
189 'lastWriteTime' => $lastWriteTime,
190 ]
191 );
192 // Forget this ParserOutput -- we will request it again if
193 // necessary in slow mode. There might be a newer entry
194 // available by that time.
195 return false;
196 }
197 }
198
199 $logger->info( $fast ? 'fast dirty output' : 'dirty output', [ 'workKey' => $this->workKey ] );
200
201 $status = Status::newGood( $parserOutput );
202 $status->warning( 'view-pool-dirty-output' );
203 $status->warning( $fast ? 'view-pool-contention' : 'view-pool-overload' );
204 return $status;
205 }
206
207}
208
210class_alias( PoolWorkArticleViewCurrent::class, 'PoolWorkArticleViewCurrent' );
A class containing constants representing the names of configuration variables.
const ParsoidSelectiveUpdateSampleRate
Name constant for the ParsoidSelectiveUpdateSampleRate setting, for use with Config::get()
Service locator for MediaWiki core services.
static getInstance()
Returns the global default instance of the top level service locator.
Service for creating WikiPage objects.
ParserOutput is a rendering of a Content object or a message.
PoolWorkArticleView for the current revision of a page, using ParserCache.
__construct(string $workKey, PageRecord $page, RevisionRecord $revision, ParserOptions $parserOptions, RevisionRenderer $revisionRenderer, ParserCache $parserCache, ILBFactory $lbFactory, ChronologyProtector $chronologyProtector, LoggerSpi $loggerSpi, WikiPageFactory $wikiPageFactory, bool $cacheable=true, bool $triggerLinksUpdate=false)
PoolCounter protected work wrapping RenderedRevision->getRevisionParserOutput.
renderRevision(?ParserOutput $previousOutput=null, bool $doSample=false, string $sourceLabel='')
Render the given revision.
Page revision base class.
getPageId( $wikiId=self::LOCAL)
Get the page ID.
The RevisionRenderer service provides access to rendered output for revisions.
Generic operation result class Has warning/error list, boolean status and arbitrary value.
Definition Status.php:54
Library for creating and parsing MW-style timestamps.
Cache for ParserOutput objects corresponding to the latest page revisions.
Set options of the Parser.
Provide a given client with protection against visible database lag.
Service provider interface to create \Psr\Log\LoggerInterface objects.
Definition Spi.php:64
Data record representing a page that is (or used to be, or could be) an editable page on a wiki.
getId( $wikiId=self::LOCAL)
Returns the page ID.
Manager of ILoadBalancer objects and, indirectly, IDatabase connections.