$edit = (object)array();
$edit->revid = $revid;
+ $edit->timestamp = wfTimestampNow();
$edit->pstContent = $content ? $content->preSaveTransform( $this->mTitle, $user, $popts ) : null;
// Save it to the parser cache
if ( $wgEnableParserCache ) {
$parserCache = ParserCache::singleton();
- $parserCache->save( $editInfo->output, $this, $editInfo->popts );
+ $parserCache->save(
+ $editInfo->output, $this, $editInfo->popts, $editInfo->timestamp, $editInfo->revid
+ );
}
// Update the links tables and other secondary data
$this->page->getTitle()->getPrefixedDBkey() ) );
}
- if ( $this->cacheable && $this->parserOutput->isCacheable() ) {
+ if ( $this->cacheable && $this->parserOutput->isCacheable() && $isCurrent ) {
ParserCache::singleton()->save(
- $this->parserOutput, $this->page, $this->parserOptions, $cacheTime );
+ $this->parserOutput, $this->page, $this->parserOptions, $cacheTime, $this->revid );
}
// Make sure file cache is not used on uncacheable content.
&& $parserOutput->isCacheable()
) {
$ctime = wfTimestamp( TS_MW, (int)$start ); // cache time
- ParserCache::singleton()->save( $parserOutput, $page, $parserOptions, $ctime );
+ ParserCache::singleton()->save(
+ $parserOutput, $page, $parserOptions, $ctime, $revision->getId()
+ );
}
}
var $mVersion = Parser::VERSION, # Compatibility check
$mCacheTime = '', # Time when this object was generated, or -1 for uncacheable. Used in ParserCache.
$mCacheExpiry = null, # Seconds after which the object should expire, use 0 for uncachable. Used in ParserCache.
- $mContainsOldMagic; # Boolean variable indicating if the input contained variables like {{CURRENTDAY}}
+ $mContainsOldMagic, # Boolean variable indicating if the input contained variables like {{CURRENTDAY}}
+ $mCacheRevisionId = null; # Revision ID that was parsed
/**
* @return string TS_MW timestamp
return wfSetVar( $this->mCacheTime, $t );
}
+ /**
+ * @since 1.23
+ * @return int|null Revision id, if any was set
+ */
+ function getCacheRevisionId() {
+ return $this->mCacheRevisionId;
+ }
+
+ /**
+ * @since 1.23
+ * @param $id int Revision id
+ */
+ function setCacheRevisionId( $id ) {
+ $this->mCacheRevisionId = $id;
+ }
+
/**
* Sets the number of seconds after which this object should expire.
* This value is used with the ParserCache.
version_compare( $this->mVersion, Parser::VERSION, "lt" );
}
+ /**
+ * Return true if this cached output object is for a different revision of
+ * the page.
+ *
+ * @todo We always return false if $this->getCacheRevisionId() is null;
+ * this prevents invalidating the whole parser cache when this change is
+ * deployed. Someday that should probably be changed.
+ *
+ * @since 1.23
+ * @param int $id the affected article's current revision id
+ * @return Boolean
+ */
+ public function isDifferentRevision( $id ) {
+ $cached = $this->getCacheRevisionId();
+ return $cached !== null && $id !== $cached;
+ }
}
$cacheTime = $optionsKey->getCacheTime();
wfDebug( "Parser options key expired, touched " . $article->getTouched() . ", epoch $wgCacheEpoch, cached $cacheTime\n" );
return false;
+ } elseif ( $optionsKey->isDifferentRevision( $article->getLatest() ) ) {
+ wfIncrStats( "pcache_miss_revid" );
+ $revId = $article->getLatest();
+ $cachedRevId = $optionsKey->getCacheRevisionId();
+ wfDebug( "ParserOutput key is for an old revision, latest $revId, cached $cachedRevId\n" );
+ return false;
}
// $optionsKey->mUsedOptions is set by save() by calling ParserOutput::getUsedOptions()
$cacheTime = $value->getCacheTime();
wfDebug( "ParserOutput key expired, touched $touched, epoch $wgCacheEpoch, cached $cacheTime\n" );
$value = false;
+ } elseif ( $value->isDifferentRevision( $article->getLatest() ) ) {
+ wfIncrStats( "pcache_miss_revid" );
+ $revId = $article->getLatest();
+ $cachedRevId = $value->getCacheRevisionId();
+ wfDebug( "ParserOutput key is for an old revision, latest $revId, cached $cachedRevId\n" );
+ $value = false;
} else {
wfIncrStats( "pcache_hit" );
}
* @param WikiPage $page
* @param ParserOptions $popts
* @param string $cacheTime Time when the cache was generated
+ * @param int $revId Revision ID that was parsed
*/
- public function save( $parserOutput, $page, $popts, $cacheTime = null ) {
+ public function save( $parserOutput, $page, $popts, $cacheTime = null, $revId = null ) {
$expire = $parserOutput->getCacheExpiry();
if ( $expire > 0 ) {
$cacheTime = $cacheTime ?: wfTimestampNow();
+ if ( !$revId ) {
+ $revision = $page->getRevision();
+ $revId = $revision ? $revision->getId() : null;
+ }
$optionsKey = new CacheTime;
$optionsKey->mUsedOptions = $parserOutput->getUsedOptions();
$optionsKey->setCacheTime( $cacheTime );
$parserOutput->setCacheTime( $cacheTime );
+ $optionsKey->setCacheRevisionId( $revId );
+ $parserOutput->setCacheRevisionId( $revId );
$optionsKey->setContainsOldMagic( $parserOutput->containsOldMagic() );
// Save the timestamp so that we don't have to load the revision row on view
$parserOutput->setTimestamp( $page->getTimestamp() );
- $parserOutput->mText .= "\n<!-- Saved in parser cache with key $parserOutputKey and timestamp $cacheTime\n -->\n";
- wfDebug( "Saved in parser cache with key $parserOutputKey and timestamp $cacheTime\n" );
+ $msg = "Saved in parser cache with key $parserOutputKey" .
+ " and timestamp $cacheTime" .
+ " and revision id $revId" .
+ "\n";
+
+ $parserOutput->mText .= "\n<!-- $msg -->\n";
+ wfDebug( $msg );
// Save the parser output
$this->mMemc->set( $parserOutputKey, $parserOutput, $expire );