28 use InvalidArgumentException;
34 use Psr\Log\LoggerInterface;
91 LoggerInterface $logger
94 $this->cache = $cache;
95 $this->cacheExpiry = $cacheExpiry;
96 $this->cacheEpoch = $cacheEpoch;
97 $this->jsonCodec = $jsonCodec;
98 $this->stats = $stats;
99 $this->logger = $logger;
105 private function incrementStats(
string $metricSuffix ) {
106 $metricSuffix = str_replace(
'.',
'_', $metricSuffix );
107 $this->stats->increment(
"RevisionOutputCache.{$this->name}.{$metricSuffix}" );
129 RevisionRecord $revision,
131 array $usedOptions =
null
135 $revId = $revision->getId();
138 throw new InvalidArgumentException(
"Revision must have an id number" );
141 return $this->cache->makeKey( $this->name, $revId, $hash );
162 RevisionRecord $revision,
164 array $usedOptions =
null
169 $revId = (string)$revision->getId();
171 return $this->cache->makeKey( $this->name, $revId, $hash );
183 public function get( RevisionRecord $revision,
ParserOptions $parserOptions ) {
184 if ( $this->cacheExpiry <= 0 ) {
189 if ( !$parserOptions->isSafeToCache() ) {
190 $this->incrementStats(
'miss.unsafe' );
194 $cacheKey = $this->makeParserOutputKey( $revision, $parserOptions );
195 $json = $this->cache->get( $cacheKey );
197 if ( $json ===
false ) {
198 $this->incrementStats(
'miss.absent' );
202 $output = $this->restoreFromJson( $json, $cacheKey, ParserOutput::class );
203 if ( $output ===
null ) {
204 $this->incrementStats(
'miss.unserialize' );
208 $cacheTime = (int)MWTimestamp::convert( TS_UNIX, $output->getCacheTime() );
209 $expiryTime = (int)MWTimestamp::convert( TS_UNIX, $this->cacheEpoch );
210 $expiryTime = max( $expiryTime, (
int)MWTimestamp::now( TS_UNIX ) - $this->cacheExpiry );
212 if ( $cacheTime < $expiryTime ) {
213 $this->incrementStats(
'miss.expired' );
217 $this->logger->debug(
'old-revision cache hit' );
218 $this->incrementStats(
'hit' );
230 RevisionRecord $revision,
232 string $cacheTime =
null
235 throw new InvalidArgumentException(
'Attempt to cache a ParserOutput with no text set!' );
238 if ( $this->cacheExpiry <= 0 ) {
243 $cacheKey = $this->makeParserOutputKey( $revision, $parserOptions );
251 $msg =
"Saved in RevisionOutputCache with key $cacheKey" .
252 " and timestamp $cacheTime" .
253 " and revision id {$revision->getId()}.";
261 if ( $expiry <= 0 ) {
262 $this->incrementStats(
'save.uncacheable' );
267 $this->incrementStats(
'save.unsafe' );
271 $json = $this->encodeAsJson( $output, $cacheKey );
272 if ( $json ===
null ) {
273 $this->incrementStats(
'save.nonserializable' );
277 $this->cache->set( $cacheKey, $json, $expiry );
278 $this->incrementStats(
'save.success' );
287 private function restoreFromJson(
string $jsonData,
string $key,
string $expectedClass ) {
290 $obj = $this->jsonCodec->unserialize( $jsonData, $expectedClass );
292 }
catch ( InvalidArgumentException $e ) {
293 $this->logger->error(
'Unable to unserialize JSON', [
294 'name' => $this->name,
296 'message' => $e->getMessage()
307 private function encodeAsJson(
CacheTime $obj,
string $key ) {
309 return $this->jsonCodec->serialize( $obj );
310 }
catch ( InvalidArgumentException $e ) {
311 $this->logger->error(
'Unable to serialize JSON', [
312 'name' => $this->name,
314 'message' => $e->getMessage(),
wfTimestampNow()
Convenience function; returns MediaWiki timestamp for the present time.
Parser cache specific expiry check.
updateCacheExpiry( $seconds)
Sets the number of seconds after which this object should expire.
setCacheTime( $t)
setCacheTime() sets the timestamp expressing when the page has been rendered.
getCacheExpiry()
Returns the number of seconds after which this object should expire.
Set options of the Parser.
isSafeToCache(array $usedOptions=null)
Test whether these options are safe to cache.
optionsHash( $forOptions, $title=null)
Generate a hash string with the values set on these ParserOptions for the keys given in the array.
hasText()
Returns true if text was passed to the constructor, or set using setText().
addCacheMessage(string $msg)
Adds a comment notice about cache state to the text of the page.
setTimestamp( $timestamp)
Multi-datacenter aware caching interface.
MediaWiki adaptation of StatsdDataFactory that provides buffering functionality.