Avoid parser cache miss that often occurs post-save

* This should not happen as doEditContent() saves the parser cache,
  so only the rare casing if incompatible options should have misses
* The bug could also cause post-save misses with edit stashing
* Avoid the second page parse post-redirect by making sure cache
  timestamps match up instead of calling time() at several points
* Likewise for null edits, which used a different code path
* Removed redundant purge in onArticleCreate() as the new row sets _touched
* Removed pointless purge in onArticleDelete() as there is no row to update
  (the method no-ops in that case to avoid contention already)

Change-Id: I178fe334a3f8691ffd9452bec30561a0c5d37c6c
This commit is contained in:
Aaron Schulz 2015-06-08 16:05:54 -07:00 committed by Ori.livneh
parent 50c6cd2458
commit 6b0163391b
3 changed files with 14 additions and 12 deletions

View file

@ -4380,9 +4380,10 @@ class Title {
/**
* Updates page_touched for this page; called from LinksUpdate.php
*
* @param integer $purgeTime TS_MW timestamp [optional]
* @return bool True if the update succeeded
*/
public function invalidateCache() {
public function invalidateCache( $purgeTime = null ) {
if ( wfReadOnly() ) {
return false;
}
@ -4394,11 +4395,13 @@ class Title {
$method = __METHOD__;
$dbw = wfGetDB( DB_MASTER );
$conds = $this->pageCond();
$dbw->onTransactionIdle( function () use ( $dbw, $conds, $method ) {
$dbw->onTransactionIdle( function () use ( $dbw, $conds, $method, $purgeTime ) {
$dbTimestamp = $dbw->timestamp( $purgeTime ?: time() );
$dbw->update(
'page',
array( 'page_touched' => $dbw->timestamp() ),
$conds,
array( 'page_touched' => $dbTimestamp ),
$conds + array( 'page_touched < ' . $dbw->addQuotes( $dbTimestamp ) ),
$method
);
} );

View file

@ -1264,10 +1264,9 @@ class WikiPage implements Page, IDBAccessObject {
$conditions['page_latest'] = $lastRevision;
}
$now = wfTimestampNow();
$row = array( /* SET */
'page_latest' => $revision->getId(),
'page_touched' => $dbw->timestamp( $now ),
'page_touched' => $dbw->timestamp( $revision->getTimestamp() ),
'page_is_new' => ( $lastRevision === 0 ) ? 1 : 0,
'page_is_redirect' => $rt !== null ? 1 : 0,
'page_len' => $len,
@ -1865,7 +1864,7 @@ class WikiPage implements Page, IDBAccessObject {
$revision = null;
// Update page_touched, this is usually implicit in the page update
// Other cache updates are done in onArticleEdit()
$this->mTitle->invalidateCache();
$this->mTitle->invalidateCache( $now );
}
} else {
// Create new article
@ -2168,9 +2167,11 @@ class WikiPage implements Page, IDBAccessObject {
$editInfo = $this->mPreparedEdit;
}
// Save it to the parser cache
// Save it to the parser cache.
// Make sure the cache time matches page_touched to avoid double parsing.
ParserCache::singleton()->save(
$editInfo->output, $this, $editInfo->popts, $editInfo->timestamp, $editInfo->revid
$editInfo->output, $this, $editInfo->popts,
$revision->getTimestamp(), $editInfo->revid
);
// Update the links tables and other secondary data
@ -3159,7 +3160,6 @@ class WikiPage implements Page, IDBAccessObject {
// Update existence markers on article/talk tabs...
$other = $title->getOtherPage();
$other->invalidateCache();
$other->purgeSquid();
$title->touchLinks();
@ -3176,7 +3176,6 @@ class WikiPage implements Page, IDBAccessObject {
// Update existence markers on article/talk tabs...
$other = $title->getOtherPage();
$other->invalidateCache();
$other->purgeSquid();
$title->touchLinks();

View file

@ -47,7 +47,7 @@ class CacheTime {
/**
* setCacheTime() sets the timestamp expressing when the page has been rendered.
* This does not control expiry, see updateCacheExpiry() for that!
* @param string $t
* @param string $t TS_MW timestamp
* @return string
*/
public function setCacheTime( $t ) {