Merge "Avoid page_touched update for HTTP GET action=purge requests"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Tue, 13 Sep 2016 06:40:52 +0000 (06:40 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Tue, 13 Sep 2016 06:40:52 +0000 (06:40 +0000)
1  2 
includes/page/Article.php
includes/page/WikiPage.php

@@@ -99,7 -99,9 +99,7 @@@ class Article implements Page 
         */
        public static function newFromID( $id ) {
                $t = Title::newFromID( $id );
 -              # @todo FIXME: Doesn't inherit right
 -              return $t == null ? null : new self( $t );
 -              # return $t == null ? null : new static( $t ); // PHP 5.3
 +              return $t == null ? null : new static( $t );
        }
  
        /**
         * Call to WikiPage function for backwards compatibility.
         * @see WikiPage::doPurge
         */
-       public function doPurge() {
-               return $this->mPage->doPurge();
+       public function doPurge( $flags = WikiPage::PURGE_ALL ) {
+               return $this->mPage->doPurge( $flags );
+       }
+       /**
+        * Call to WikiPage function for backwards compatibility.
+        * @see WikiPage::getLastPurgeTimestamp
+        */
+       public function getLastPurgeTimestamp() {
+               return $this->mPage->getLastPurgeTimestamp();
        }
  
        /**
@@@ -83,6 -83,11 +83,11 @@@ class WikiPage implements Page, IDBAcce
         */
        protected $mLinksUpdated = '19700101000000';
  
+       const PURGE_CDN_CACHE = 1; // purge CDN cache for page variant URLs
+       const PURGE_CLUSTER_PCACHE = 2; // purge parser cache in the local datacenter
+       const PURGE_GLOBAL_PCACHE = 4; // set page_touched to clear parser cache in all datacenters
+       const PURGE_ALL = 7;
        /**
         * Constructor and clear the article
         * @param Title $title Reference to a Title object.
         * @return bool
         */
        public function hasViewableContent() {
 -              return $this->exists() || $this->mTitle->isAlwaysKnown();
 +              return $this->mTitle->isKnown();
        }
  
        /**
  
        /**
         * Perform the actions of a page purging
+        * @param integer $flags Bitfield of WikiPage::PURGE_* constants
         * @return bool
         */
-       public function doPurge() {
+       public function doPurge( $flags = self::PURGE_ALL ) {
                if ( !Hooks::run( 'ArticlePurge', [ &$this ] ) ) {
                        return false;
                }
  
-               $this->mTitle->invalidateCache();
+               if ( ( $flags & self::PURGE_GLOBAL_PCACHE ) == self::PURGE_GLOBAL_PCACHE ) {
+                       // Set page_touched in the database to invalidate all DC caches
+                       $this->mTitle->invalidateCache();
+               } elseif ( ( $flags & self::PURGE_CLUSTER_PCACHE ) == self::PURGE_CLUSTER_PCACHE ) {
+                       // Delete the parser options key in the local cluster to invalidate the DC cache
+                       ParserCache::singleton()->deleteOptionsKey( $this );
+                       // Avoid sending HTTP 304s in ViewAction to the client who just issued the purge
+                       $cache = ObjectCache::getLocalClusterInstance();
+                       $cache->set(
+                               $cache->makeKey( 'page', 'last-dc-purge', $this->getId() ),
+                               wfTimestamp( TS_MW ),
+                               $cache::TTL_HOUR
+                       );
+               }
  
-               // Clear file cache
-               HTMLFileCache::clearFileCache( $this->getTitle() );
-               // Send purge after above page_touched update was committed
-               DeferredUpdates::addUpdate(
-                       new CdnCacheUpdate( $this->mTitle->getCdnUrls() ),
-                       DeferredUpdates::PRESEND
-               );
+               if ( ( $flags & self::PURGE_CDN_CACHE ) == self::PURGE_CDN_CACHE ) {
+                       // Clear any HTML file cache
+                       HTMLFileCache::clearFileCache( $this->getTitle() );
+                       // Send purge after any page_touched above update was committed
+                       DeferredUpdates::addUpdate(
+                               new CdnCacheUpdate( $this->mTitle->getCdnUrls() ),
+                               DeferredUpdates::PRESEND
+                       );
+               }
  
                if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) {
                        // @todo move this logic to MessageCache
                return true;
        }
  
+       /**
+        * Get the last time a user explicitly purged the page via action=purge
+        *
+        * @return string|bool TS_MW timestamp or false
+        * @since 1.28
+        */
+       public function getLastPurgeTimestamp() {
+               $cache = ObjectCache::getLocalClusterInstance();
+               return $cache->get( $cache->makeKey( 'page', 'last-dc-purge', $this->getId() ) );
+       }
        /**
         * Insert a new empty page record for this article.
         * This *must* be followed up by creating a revision
                Hooks::run( 'WikiPageDeletionUpdates', [ $this, $content, &$updates ] );
                return $updates;
        }
 +
 +      /**
 +       * Whether this content displayed on this page
 +       * comes from the local database
 +       *
 +       * @since 1.28
 +       * @return bool
 +       */
 +      public function isLocal() {
 +              return true;
 +      }
  }