aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAaron Schulz <aschulz@wikimedia.org>2019-03-14 17:23:26 -0700
committerJames D. Forrester <jforrester@wikimedia.org>2019-08-06 13:45:27 -0700
commit35da1bbd7cb8b4414c4fbcf331473f1024bc638d (patch)
treef903765d437301b1bff67ebea4fd895ce64132d9
parenta6b45d2a20c9be095431ac60ba0a4f5951b5f387 (diff)
downloadmediawikicore-35da1bbd7cb8b4414c4fbcf331473f1024bc638d.tar.gz
mediawikicore-35da1bbd7cb8b4414c4fbcf331473f1024bc638d.zip
Add small HtmlCacheUpdater service class to normalize purging code
The purge() method handles purging of both file cache and CDN, using a PRESEND deferred update. This avoids code duplication and missing file cache purge calls. Also: * Migrate HTMLCacheUpdate callers to just directly using HTMLCacheUpdateJob * Add HtmlFileCacheUpdate class and defer such updates just like with CDN * Simplify HTMLCacheUpdate constructor parameters * Remove BacklinkCache::clear() calls which do nothing since the backlink query does not actually happen until the job runs Change-Id: Ic453b189a40109a73a9426538608eea87a76befa
-rw-r--r--RELEASE-NOTES-1.343
-rw-r--r--autoload.php2
-rw-r--r--includes/MediaWikiServices.php9
-rw-r--r--includes/ServiceWiring.php4
-rw-r--r--includes/Title.php21
-rw-r--r--includes/cache/HTMLFileCache.php24
-rw-r--r--includes/cache/HtmlCacheUpdater.php94
-rw-r--r--includes/deferred/CdnCacheUpdate.php14
-rw-r--r--includes/deferred/HTMLCacheUpdate.php27
-rw-r--r--includes/deferred/HtmlFileCacheUpdate.php61
-rw-r--r--includes/deferred/LinksUpdate.php9
-rw-r--r--includes/filerepo/file/File.php9
-rw-r--r--includes/filerepo/file/LocalFile.php35
-rw-r--r--includes/jobqueue/jobs/HTMLCacheUpdateJob.php23
-rw-r--r--includes/page/PageArchive.php8
-rw-r--r--includes/page/WikiFilePage.php7
-rw-r--r--includes/page/WikiPage.php55
-rw-r--r--includes/revisiondelete/RevDelFileList.php5
-rw-r--r--includes/revisiondelete/RevDelRevisionList.php6
19 files changed, 298 insertions, 118 deletions
diff --git a/RELEASE-NOTES-1.34 b/RELEASE-NOTES-1.34
index 8ecc469d67b0..56a886e44729 100644
--- a/RELEASE-NOTES-1.34
+++ b/RELEASE-NOTES-1.34
@@ -92,6 +92,8 @@ For notes on 1.33.x and older releases, see HISTORY.
to add fields to Special:Mute.
* (T100896) Skin authors can define custom OOUI themes using OOUIThemePaths.
See <https://www.mediawiki.org/wiki/OOUI/Themes> for details.
+* The HtmlCacheUpdater service was added to unify the logic of purging CDN cache
+ and HTML file cache to simplify callers and make them more consistent.
=== External library changes in 1.34 ===
@@ -435,6 +437,7 @@ because of Phabricator reports.
* SearchEngine::textAlreadyUpdatedForIndex() is deprecated, given the
deprecation above this method is no longer needed/called and should not be
implemented by SearchEngine implementation.
+* Title::purgeSquid is deprecated. Use MediaWikiServices::getHtmlCacheUpdater.
=== Other changes in 1.34 ===
* …
diff --git a/autoload.php b/autoload.php
index 0208a6d783aa..ed6bb12aa642 100644
--- a/autoload.php
+++ b/autoload.php
@@ -642,6 +642,8 @@ $wgAutoloadLocalClasses = [
'Hooks' => __DIR__ . '/includes/Hooks.php',
'Html' => __DIR__ . '/includes/Html.php',
'HtmlArmor' => __DIR__ . '/includes/libs/HtmlArmor.php',
+ 'HtmlCacheUpdater' => __DIR__ . '/includes/cache/HtmlCacheUpdater.php',
+ 'HtmlFileCacheUpdate' => __DIR__ . '/includes/deferred/HtmlFileCacheUpdate.php',
'Http' => __DIR__ . '/includes/http/Http.php',
'HttpError' => __DIR__ . '/includes/exception/HttpError.php',
'HttpStatus' => __DIR__ . '/includes/libs/HttpStatus.php',
diff --git a/includes/MediaWikiServices.php b/includes/MediaWikiServices.php
index 7fda45280ac5..fb30199ffe79 100644
--- a/includes/MediaWikiServices.php
+++ b/includes/MediaWikiServices.php
@@ -68,6 +68,7 @@ use Wikimedia\Services\NoSuchServiceException;
use MediaWiki\Interwiki\InterwikiLookup;
use MagicWordFactory;
use MediaWiki\Storage\PageEditStash;
+use HtmlCacheUpdater;
/**
* Service locator for MediaWiki core services.
@@ -596,6 +597,14 @@ class MediaWikiServices extends ServiceContainer {
}
/**
+ * @return HtmlCacheUpdater
+ * @since 1.34
+ */
+ public function getHtmlCacheUpdater() {
+ return $this->getService( 'HtmlCacheUpdater' );
+ }
+
+ /**
* @since 1.31
* @return HttpRequestFactory
*/
diff --git a/includes/ServiceWiring.php b/includes/ServiceWiring.php
index 9073de1c0eac..d6b4d65433ce 100644
--- a/includes/ServiceWiring.php
+++ b/includes/ServiceWiring.php
@@ -218,6 +218,10 @@ return [
return new GenderCache( $services->getNamespaceInfo() );
},
+ 'HtmlCacheUpdater' => function ( MediaWikiServices $services ) : HtmlCacheUpdater {
+ return new HtmlCacheUpdater();
+ },
+
'HttpRequestFactory' =>
function ( MediaWikiServices $services ) : HttpRequestFactory {
return new HttpRequestFactory();
diff --git a/includes/Title.php b/includes/Title.php
index 281f75bac1e7..674767d37b7b 100644
--- a/includes/Title.php
+++ b/includes/Title.php
@@ -3432,12 +3432,10 @@ class Title implements LinkTarget, IDBAccessObject {
/**
* Purge all applicable CDN URLs
+ * @deprecated 1.34 Use HtmlCacheUpdater
*/
public function purgeSquid() {
- DeferredUpdates::addUpdate(
- new CdnCacheUpdate( $this->getCdnUrls() ),
- DeferredUpdates::PRESEND
- );
+ MediaWikiServices::getInstance()->getHtmlCacheUpdater()->purge( $this->getCdnUrls() );
}
/**
@@ -4245,12 +4243,21 @@ class Title implements LinkTarget, IDBAccessObject {
* on the number of links. Typically called on create and delete.
*/
public function touchLinks() {
- DeferredUpdates::addUpdate( new HTMLCacheUpdate( $this, 'pagelinks', 'page-touch' ) );
+ $jobs = [];
+ $jobs[] = HTMLCacheUpdateJob::newForBacklinks(
+ $this,
+ 'pagelinks',
+ [ 'causeAction' => 'page-touch' ]
+ );
if ( $this->mNamespace == NS_CATEGORY ) {
- DeferredUpdates::addUpdate(
- new HTMLCacheUpdate( $this, 'categorylinks', 'category-touch' )
+ $jobs[] = HTMLCacheUpdateJob::newForBacklinks(
+ $this,
+ 'categorylinks',
+ [ 'causeAction' => 'category-touch' ]
);
}
+
+ JobQueueGroup::singleton()->lazyPush( $jobs );
}
/**
diff --git a/includes/cache/HTMLFileCache.php b/includes/cache/HTMLFileCache.php
index a0d61b259efd..6d0b87e6e66c 100644
--- a/includes/cache/HTMLFileCache.php
+++ b/includes/cache/HTMLFileCache.php
@@ -220,20 +220,32 @@ class HTMLFileCache extends FileCacheBase {
}
/**
+ * @param string[] $prefixedDbKeys List of prefixed DB keys for pages to purge
+ * @since 1.34
+ */
+ public static function purge( array $prefixedDbKeys ) {
+ foreach ( $prefixedDbKeys as $prefixedDbKey ) {
+ foreach ( self::cacheablePageActions() as $type ) {
+ $fc = new self( $prefixedDbKey, $type );
+ $fc->clearCache();
+ }
+ }
+ }
+
+ /**
* Clear the file caches for a page for all actions
- * @param Title $title
+ * @param Traversable|Title[]|Title $titles
* @return bool Whether $wgUseFileCache is enabled
*/
- public static function clearFileCache( Title $title ) {
+ public static function clearFileCache( $titles ) {
$config = MediaWikiServices::getInstance()->getMainConfig();
-
if ( !$config->get( 'UseFileCache' ) ) {
return false;
}
- foreach ( self::cacheablePageActions() as $type ) {
- $fc = new self( $title, $type );
- $fc->clearCache();
+ $titleIterator = ( $titles instanceof Title ) ? [ $titles ] : $titles;
+ foreach ( $titleIterator as $title ) {
+ self::purge( [ $title->getPrefixedDBkey() ] );
}
return true;
diff --git a/includes/cache/HtmlCacheUpdater.php b/includes/cache/HtmlCacheUpdater.php
new file mode 100644
index 000000000000..b04428c99b38
--- /dev/null
+++ b/includes/cache/HtmlCacheUpdater.php
@@ -0,0 +1,94 @@
+<?php
+/**
+ * HTML/file cache invalidation of cacheable variant/action URLs for a page
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Cache
+ */
+
+/**
+ * Class to invalidate the HTML/file cache of cacheable variant/action URLs for a page
+ *
+ * @ingroup Cache
+ * @since 1.34
+ */
+class HtmlCacheUpdater {
+ /** @var int Purge after the main transaction round and respect $wgCdnReboundPurgeDelay */
+ const ISOLATION_AND_LAG_AWARE = 1;
+ /** @var int Purge immediately and only once (ignore $wgCdnReboundPurgeDelay) */
+ const IMMEDIATE_WITHOUT_REBOUND = 2;
+
+ /**
+ * Purge CDN/HTMLFileCache for a URL, Title, or iteratable of URL or Title entries
+ *
+ * String entries will be treated as URLs to be purged from the CDN layer.
+ * For Title entries, all cacheable canonical URLs associated with the page
+ * will be purged from the CDN and HTMLFileCache.
+ *
+ * The cache purges are queued as PRESEND deferred updates so that they run after the
+ * main database transaction round of LBFactory. This reduces the chance of race conditions
+ * where a stale value is re-populated before commit. Depending on $wgCdnReboundPurgeDelay,
+ * a secondary set of purges might be issued several seconds later through the use of a
+ * delayed job. This is used to mitigate the effects of DB replication lag as well as
+ * multiple layers of CDN proxies. All deferred CDN purges are combined and de-duplicated
+ * into a single DeferrableUpdate instance. This improves HTTP PURGE request pipelining.
+ *
+ * Use the IMMEDIATE_WITHOUT_REBOUND class constant to instantly issue the purges instead
+ * and skip the use of any secondary purges regardless of $wgCdnReboundPurgeDelay.
+ *
+ * @param Traversable|Title[]|Title|string[]|string $entries
+ * @param int $mode ISOLATION_AND_LAG_AWARE or IMMEDIATE_WITHOUT_REBOUND class constant
+ */
+ public function purge( $entries, $mode = self::ISOLATION_AND_LAG_AWARE ) {
+ $urls = [];
+ $titles = [];
+ if ( is_string( $entries ) ) {
+ $urls = [ $entries ];
+ } elseif ( $entries instanceof Title ) {
+ $titles = [ $entries ];
+ } elseif ( $entries instanceof TitleArray ) {
+ $titles = $entries; // save memory
+ } else {
+ foreach ( $entries as $entry ) {
+ if ( is_string( $entry ) ) {
+ $urls[] = $entry;
+ } else {
+ $titles[] = $entry;
+ }
+ }
+ }
+
+ if ( $mode === self::IMMEDIATE_WITHOUT_REBOUND ) {
+ HTMLFileCache::clearFileCache( $titles );
+ foreach ( $titles as $title ) {
+ /** @var Title $title */
+ $urls = array_merge( $urls, $title->getCdnUrls() );
+ }
+ CdnCacheUpdate::purge( $urls ); // purge once (no "rebound" purges)
+ } else {
+ DeferredUpdates::addUpdate(
+ HtmlFileCacheUpdate::newFromTitles( $titles ),
+ DeferredUpdates::PRESEND
+ );
+ DeferredUpdates::addUpdate(
+ CdnCacheUpdate::newFromTitles( $titles, $urls ),
+ DeferredUpdates::PRESEND
+ );
+ }
+ }
+}
diff --git a/includes/deferred/CdnCacheUpdate.php b/includes/deferred/CdnCacheUpdate.php
index 66ce9a3ddf83..a867f2062ef4 100644
--- a/includes/deferred/CdnCacheUpdate.php
+++ b/includes/deferred/CdnCacheUpdate.php
@@ -24,12 +24,12 @@ use Wikimedia\Assert\Assert;
use MediaWiki\MediaWikiServices;
/**
- * Handles purging appropriate CDN URLs given a title (or titles)
+ * Handles purging the appropriate CDN objects given a list of URLs or Title instances
* @ingroup Cache
*/
class CdnCacheUpdate implements DeferrableUpdate, MergeableUpdate {
/** @var string[] Collection of URLs to purge */
- protected $urls = [];
+ private $urls = [];
/**
* @param string[] $urlArr Collection of URLs to purge
@@ -59,12 +59,9 @@ class CdnCacheUpdate implements DeferrableUpdate, MergeableUpdate {
$urlArr = array_merge( $urlArr, $title->getCdnUrls() );
}
- return new CdnCacheUpdate( $urlArr );
+ return new self( $urlArr );
}
- /**
- * Purges the list of URLs passed to the constructor.
- */
public function doUpdate() {
global $wgCdnReboundPurgeDelay;
@@ -98,10 +95,9 @@ class CdnCacheUpdate implements DeferrableUpdate, MergeableUpdate {
wfDebugLog( 'squid', __METHOD__ . ': ' . implode( ' ', $urlArr ) );
// Reliably broadcast the purge to all edge nodes
- $relayer = MediaWikiServices::getInstance()->getEventRelayerGroup()
- ->getRelayer( 'cdn-url-purges' );
$ts = microtime( true );
- $relayer->notifyMulti(
+ $relayerGroup = MediaWikiServices::getInstance()->getEventRelayerGroup();
+ $relayerGroup->getRelayer( 'cdn-url-purges' )->notifyMulti(
'cdn-url-purges',
array_map(
function ( $url ) use ( $ts ) {
diff --git a/includes/deferred/HTMLCacheUpdate.php b/includes/deferred/HTMLCacheUpdate.php
index 29846bfb77f8..3dd533db7e78 100644
--- a/includes/deferred/HTMLCacheUpdate.php
+++ b/includes/deferred/HTMLCacheUpdate.php
@@ -22,39 +22,32 @@
*/
/**
- * Class to invalidate the HTML cache of all the pages linking to a given title.
+ * Class to invalidate the HTML/file cache of all the pages linking to a given title.
*
* @ingroup Cache
+ * @deprecated Since 1.34; Enqueue jobs from HTMLCacheUpdateJob::newForBacklinks instead
*/
class HTMLCacheUpdate extends DataUpdate {
/** @var Title */
- public $mTitle;
-
+ private $title;
/** @var string */
- public $mTable;
+ private $table;
/**
- * @param Title $titleTo
+ * @param Title $title
* @param string $table
- * @param string $causeAction Triggering action
- * @param string $causeAgent Triggering user
*/
- function __construct(
- Title $titleTo, $table, $causeAction = 'unknown', $causeAgent = 'unknown'
- ) {
- $this->mTitle = $titleTo;
- $this->mTable = $table;
- $this->causeAction = $causeAction;
- $this->causeAgent = $causeAgent;
+ public function __construct( Title $title, $table ) {
+ $this->title = $title;
+ $this->table = $table;
}
public function doUpdate() {
$job = HTMLCacheUpdateJob::newForBacklinks(
- $this->mTitle,
- $this->mTable,
+ $this->title,
+ $this->table,
[ 'causeAction' => $this->getCauseAction(), 'causeAgent' => $this->getCauseAgent() ]
);
-
JobQueueGroup::singleton()->lazyPush( $job );
}
}
diff --git a/includes/deferred/HtmlFileCacheUpdate.php b/includes/deferred/HtmlFileCacheUpdate.php
new file mode 100644
index 000000000000..7be8b61eaba9
--- /dev/null
+++ b/includes/deferred/HtmlFileCacheUpdate.php
@@ -0,0 +1,61 @@
+<?php
+/**
+ * HTMLFileCache cache purging
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+use MediaWiki\MediaWikiServices;
+
+/**
+ * Handles purging the appropriate HTMLFileCache files given a list of titles
+ * @ingroup Cache
+ */
+class HtmlFileCacheUpdate implements DeferrableUpdate {
+ /** @var string[] Collection of prefixed DB keys for the pages to purge */
+ private $prefixedDbKeys = [];
+
+ /**
+ * @param string[] $prefixedDbKeys
+ */
+ public function __construct( array $prefixedDbKeys ) {
+ $this->prefixedDbKeys = $prefixedDbKeys;
+ }
+
+ /**
+ * Create an update object from an array of Title objects, or a TitleArray object
+ *
+ * @param Traversable|Title[] $titles
+ * @return HtmlFileCacheUpdate
+ */
+ public static function newFromTitles( $titles ) {
+ $prefixedDbKeys = [];
+ foreach ( $titles as $title ) {
+ $prefixedDbKeys[] = $title->getPrefixedDBkey();
+ }
+
+ return new self( $prefixedDbKeys );
+ }
+
+ public function doUpdate() {
+ $config = MediaWikiServices::getInstance()->getMainConfig();
+ if ( $config->get( 'UseFileCache' ) ) {
+ HTMLFileCache::purge( $this->prefixedDbKeys );
+ }
+ }
+}
diff --git a/includes/deferred/LinksUpdate.php b/includes/deferred/LinksUpdate.php
index 74e236fd4d74..ff293cb9d87c 100644
--- a/includes/deferred/LinksUpdate.php
+++ b/includes/deferred/LinksUpdate.php
@@ -1066,6 +1066,7 @@ class LinksUpdate extends DataUpdate {
private function invalidateProperties( $changed ) {
global $wgPagePropLinkInvalidations;
+ $jobs = [];
foreach ( $changed as $name => $value ) {
if ( isset( $wgPagePropLinkInvalidations[$name] ) ) {
$inv = $wgPagePropLinkInvalidations[$name];
@@ -1073,12 +1074,16 @@ class LinksUpdate extends DataUpdate {
$inv = [ $inv ];
}
foreach ( $inv as $table ) {
- DeferredUpdates::addUpdate(
- new HTMLCacheUpdate( $this->mTitle, $table, 'page-props' )
+ $jobs[] = HTMLCacheUpdateJob::newForBacklinks(
+ $this->mTitle,
+ $table,
+ [ 'causeAction' => 'page-props' ]
);
}
}
}
+
+ JobQueueGroup::singleton()->lazyPush( $jobs );
}
/**
diff --git a/includes/filerepo/file/File.php b/includes/filerepo/file/File.php
index ee7ee6f90dcd..eca546494255 100644
--- a/includes/filerepo/file/File.php
+++ b/includes/filerepo/file/File.php
@@ -1453,7 +1453,7 @@ abstract class File implements IDBAccessObject {
$title = $this->getTitle();
if ( $title ) {
$title->invalidateCache();
- $title->purgeSquid();
+ MediaWikiServices::getInstance()->getHtmlCacheUpdater()->purge( $title );
}
}
@@ -1469,9 +1469,12 @@ abstract class File implements IDBAccessObject {
// Purge cache of all pages using this file
$title = $this->getTitle();
if ( $title ) {
- DeferredUpdates::addUpdate(
- new HTMLCacheUpdate( $title, 'imagelinks', 'file-purge' )
+ $job = HTMLCacheUpdateJob::newForBacklinks(
+ $title,
+ 'imagelinks',
+ [ 'causeAction' => 'file-purge' ]
);
+ JobQueueGroup::singleton()->lazyPush( $job );
}
}
diff --git a/includes/filerepo/file/LocalFile.php b/includes/filerepo/file/LocalFile.php
index 54fc251f4bd1..989d22283fc4 100644
--- a/includes/filerepo/file/LocalFile.php
+++ b/includes/filerepo/file/LocalFile.php
@@ -1047,10 +1047,7 @@ class LocalFile extends File {
$this->purgeThumbnails( $options );
// Purge CDN cache for this file
- DeferredUpdates::addUpdate(
- new CdnCacheUpdate( [ $this->getUrl() ] ),
- DeferredUpdates::PRESEND
- );
+ MediaWikiServices::getInstance()->getHtmlCacheUpdater()->purge( $this->getUrl() );
}
/**
@@ -1073,7 +1070,7 @@ class LocalFile extends File {
foreach ( $files as $file ) {
$urls[] = $this->getArchiveThumbUrl( $archiveName, $file );
}
- DeferredUpdates::addUpdate( new CdnCacheUpdate( $urls ), DeferredUpdates::PRESEND );
+ MediaWikiServices::getInstance()->getHtmlCacheUpdater()->purge( $urls );
}
/**
@@ -1105,7 +1102,7 @@ class LocalFile extends File {
$this->purgeThumbList( $dir, $files );
// Purge the CDN
- DeferredUpdates::addUpdate( new CdnCacheUpdate( $urls ), DeferredUpdates::PRESEND );
+ MediaWikiServices::getInstance()->getHtmlCacheUpdater()->purge( $urls );
}
/**
@@ -1725,8 +1722,9 @@ class LocalFile extends File {
}
} else {
# Existing file page: invalidate description page cache
- $wikiPage->getTitle()->invalidateCache();
- $wikiPage->getTitle()->purgeSquid();
+ $title = $wikiPage->getTitle();
+ $title->invalidateCache();
+ MediaWikiServices::getInstance()->getHtmlCacheUpdater()->purge( $title );
# Allow the new file version to be patrolled from the page footer
Article::purgePatrolFooterCache( $descId );
}
@@ -1774,10 +1772,8 @@ class LocalFile extends File {
# Delete old thumbnails
$this->purgeThumbnails();
# Remove the old file from the CDN cache
- DeferredUpdates::addUpdate(
- new CdnCacheUpdate( [ $this->getUrl() ] ),
- DeferredUpdates::PRESEND
- );
+ MediaWikiServices::getInstance()
+ ->getHtmlCacheUpdater()->purge( $this->getUrl() );
} else {
# Update backlink pages pointing to this title if created
LinksUpdate::queueRecursiveJobsForTable(
@@ -1800,9 +1796,12 @@ class LocalFile extends File {
}
# Invalidate cache for all pages using this file
- DeferredUpdates::addUpdate(
- new HTMLCacheUpdate( $this->getTitle(), 'imagelinks', 'file-upload' )
+ $job = HTMLCacheUpdateJob::newForBacklinks(
+ $this->getTitle(),
+ 'imagelinks',
+ [ 'causeAction' => 'file-upload', 'causeAgent' => $user->getName() ]
);
+ JobQueueGroup::singleton()->lazyPush( $job );
return Status::newGood();
}
@@ -2004,7 +2003,7 @@ class LocalFile extends File {
foreach ( $archiveNames as $archiveName ) {
$purgeUrls[] = $this->getArchiveUrl( $archiveName );
}
- DeferredUpdates::addUpdate( new CdnCacheUpdate( $purgeUrls ), DeferredUpdates::PRESEND );
+ MediaWikiServices::getInstance()->getHtmlCacheUpdater()->purge( $purgeUrls );
return $status;
}
@@ -2041,10 +2040,8 @@ class LocalFile extends File {
$this->purgeDescription();
}
- DeferredUpdates::addUpdate(
- new CdnCacheUpdate( [ $this->getArchiveUrl( $archiveName ) ] ),
- DeferredUpdates::PRESEND
- );
+ $url = $this->getArchiveUrl( $archiveName );
+ MediaWikiServices::getInstance()->getHtmlCacheUpdater()->purge( $url );
return $status;
}
diff --git a/includes/jobqueue/jobs/HTMLCacheUpdateJob.php b/includes/jobqueue/jobs/HTMLCacheUpdateJob.php
index 73fa947790bb..a2e47343db21 100644
--- a/includes/jobqueue/jobs/HTMLCacheUpdateJob.php
+++ b/includes/jobqueue/jobs/HTMLCacheUpdateJob.php
@@ -25,7 +25,7 @@
use MediaWiki\MediaWikiServices;
/**
- * Job to purge the cache for all pages that link to or use another page or file
+ * Job to purge the HTML/file cache for all pages that link to or use another page or file
*
* This job comes in a few variants:
* - a) Recursive jobs to purge caches for backlink pages for a given title.
@@ -110,7 +110,7 @@ class HTMLCacheUpdateJob extends Job {
* @param array $pages Map of (page ID => (namespace, DB key)) entries
*/
protected function invalidateTitles( array $pages ) {
- global $wgUpdateRowsPerQuery, $wgUseFileCache, $wgPageLanguageUseDB;
+ global $wgUpdateRowsPerQuery, $wgPageLanguageUseDB;
// Get all page IDs in this query into an array
$pageIds = array_keys( $pages );
@@ -160,20 +160,11 @@ class HTMLCacheUpdateJob extends Job {
__METHOD__
) );
- // Update CDN; call purge() directly so as to not bother with secondary purges
- $urls = [];
- foreach ( $titleArray as $title ) {
- /** @var Title $title */
- $urls = array_merge( $urls, $title->getCdnUrls() );
- }
- CdnCacheUpdate::purge( $urls );
-
- // Update file cache
- if ( $wgUseFileCache ) {
- foreach ( $titleArray as $title ) {
- HTMLFileCache::clearFileCache( $title );
- }
- }
+ // Update CDN and file caches (avoiding secondary purge overhead)
+ MediaWikiServices::getInstance()->getHtmlCacheUpdater()->purge(
+ $titleArray,
+ HtmlCacheUpdater::IMMEDIATE_WITHOUT_REBOUND
+ );
}
public function getDeduplicationInfo() {
diff --git a/includes/page/PageArchive.php b/includes/page/PageArchive.php
index d69a433d9ce8..19e417abe466 100644
--- a/includes/page/PageArchive.php
+++ b/includes/page/PageArchive.php
@@ -756,10 +756,14 @@ class PageArchive {
Hooks::run( 'ArticleUndelete',
[ &$this->title, $created, $comment, $oldPageId, $restoredPages ] );
+
if ( $this->title->getNamespace() == NS_FILE ) {
- DeferredUpdates::addUpdate(
- new HTMLCacheUpdate( $this->title, 'imagelinks', 'file-restore' )
+ $job = HTMLCacheUpdateJob::newForBacklinks(
+ $this->title,
+ 'imagelinks',
+ [ 'causeAction' => 'imagelinks', 'causeAgent' => 'file-restore' ]
);
+ JobQueueGroup::singleton()->lazyPush( $job );
}
}
diff --git a/includes/page/WikiFilePage.php b/includes/page/WikiFilePage.php
index acd506ba79a0..fd9f7b24d8f3 100644
--- a/includes/page/WikiFilePage.php
+++ b/includes/page/WikiFilePage.php
@@ -176,9 +176,12 @@ class WikiFilePage extends WikiPage {
if ( $this->mFile->exists() ) {
wfDebug( 'ImagePage::doPurge purging ' . $this->mFile->getName() . "\n" );
- DeferredUpdates::addUpdate(
- new HTMLCacheUpdate( $this->mTitle, 'imagelinks', 'file-purge' )
+ $job = HTMLCacheUpdateJob::newForBacklinks(
+ $this->mTitle,
+ 'imagelinks',
+ [ 'causeAction' => 'file-purge' ]
);
+ JobQueueGroup::singleton()->lazyPush( $job );
} else {
wfDebug( 'ImagePage::doPurge no image for '
. $this->mFile->getName() . "; limiting purge to cache only\n" );
diff --git a/includes/page/WikiPage.php b/includes/page/WikiPage.php
index 3bc9f7c0f8d7..33fd4721d4bf 100644
--- a/includes/page/WikiPage.php
+++ b/includes/page/WikiPage.php
@@ -1294,13 +1294,8 @@ class WikiPage implements Page, IDBAccessObject {
$this->mTitle->invalidateCache();
- // 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
- );
+ // Clear file cache and send purge after above page_touched update was committed
+ MediaWikiServices::getInstance()->getHtmlCacheUpdater()->purge( $this->mTitle );
if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) {
$messageCache = MessageCache::singleton();
@@ -3384,18 +3379,20 @@ class WikiPage implements Page, IDBAccessObject {
// Update existence markers on article/talk tabs...
$other = $title->getOtherPage();
- $other->purgeSquid();
+ MediaWikiServices::getInstance()->getHtmlCacheUpdater()->purge( [ $title, $other ] );
$title->touchLinks();
- $title->purgeSquid();
$title->deleteTitleProtection();
MediaWikiServices::getInstance()->getLinkCache()->invalidateTitle( $title );
// Invalidate caches of articles which include this page
- DeferredUpdates::addUpdate(
- new HTMLCacheUpdate( $title, 'templatelinks', 'page-create' )
+ $job = HTMLCacheUpdateJob::newForBacklinks(
+ $title,
+ 'templatelinks',
+ [ 'causeAction' => 'page-create' ]
);
+ JobQueueGroup::singleton()->lazyPush( $job );
if ( $title->getNamespace() == NS_CATEGORY ) {
// Load the Category object, which will schedule a job to create
@@ -3415,19 +3412,14 @@ class WikiPage implements Page, IDBAccessObject {
// TODO: move this into a PageEventEmitter service
// Update existence markers on article/talk tabs...
- // Clear Backlink cache first so that purge jobs use more up-to-date backlink information
- BacklinkCache::get( $title )->clear();
$other = $title->getOtherPage();
- $other->purgeSquid();
+ MediaWikiServices::getInstance()->getHtmlCacheUpdater()->purge( [ $title, $other ] );
$title->touchLinks();
- $title->purgeSquid();
MediaWikiServices::getInstance()->getLinkCache()->invalidateTitle( $title );
- // File cache
- HTMLFileCache::clearFileCache( $title );
InfoAction::invalidateCache( $title );
// Messages
@@ -3437,9 +3429,12 @@ class WikiPage implements Page, IDBAccessObject {
// Images
if ( $title->getNamespace() == NS_FILE ) {
- DeferredUpdates::addUpdate(
- new HTMLCacheUpdate( $title, 'imagelinks', 'page-delete' )
+ $job = HTMLCacheUpdateJob::newForBacklinks(
+ $title,
+ 'imagelinks',
+ [ 'causeAction' => 'page-delete' ]
);
+ JobQueueGroup::singleton()->lazyPush( $job );
}
// User talk pages
@@ -3472,26 +3467,28 @@ class WikiPage implements Page, IDBAccessObject {
) {
// TODO: move this into a PageEventEmitter service
- if ( $slotsChanged === null || in_array( SlotRecord::MAIN, $slotsChanged ) ) {
+ $jobs = [];
+ if ( $slotsChanged === null || in_array( SlotRecord::MAIN, $slotsChanged ) ) {
// Invalidate caches of articles which include this page.
// Only for the main slot, because only the main slot is transcluded.
// TODO: MCR: not true for TemplateStyles! [SlotHandler]
- DeferredUpdates::addUpdate(
- new HTMLCacheUpdate( $title, 'templatelinks', 'page-edit' )
+ $jobs[] = HTMLCacheUpdateJob::newForBacklinks(
+ $title,
+ 'templatelinks',
+ [ 'causeAction' => 'page-edit' ]
);
}
-
// Invalidate the caches of all pages which redirect here
- DeferredUpdates::addUpdate(
- new HTMLCacheUpdate( $title, 'redirect', 'page-edit' )
+ $jobs[] = HTMLCacheUpdateJob::newForBacklinks(
+ $title,
+ 'redirect',
+ [ 'causeAction' => 'page-edit' ]
);
+ JobQueueGroup::singleton()->lazyPush( $jobs );
MediaWikiServices::getInstance()->getLinkCache()->invalidateTitle( $title );
- // Purge CDN for this page only
- $title->purgeSquid();
- // Clear file cache for this page only
- HTMLFileCache::clearFileCache( $title );
+ MediaWikiServices::getInstance()->getHtmlCacheUpdater()->purge( $title );
// Purge ?action=info cache
$revid = $revision ? $revision->getId() : null;
diff --git a/includes/revisiondelete/RevDelFileList.php b/includes/revisiondelete/RevDelFileList.php
index ca7bc040d0fa..d69fa36ca5f0 100644
--- a/includes/revisiondelete/RevDelFileList.php
+++ b/includes/revisiondelete/RevDelFileList.php
@@ -122,10 +122,7 @@ class RevDelFileList extends RevDelList {
$file->purgeOldThumbnails( $archiveName );
$purgeUrls[] = $file->getArchiveUrl( $archiveName );
}
- DeferredUpdates::addUpdate(
- new CdnCacheUpdate( $purgeUrls ),
- DeferredUpdates::PRESEND
- );
+ MediaWikiServices::getInstance()->getHtmlCacheUpdater()->purge( $purgeUrls );
return Status::newGood();
}
diff --git a/includes/revisiondelete/RevDelRevisionList.php b/includes/revisiondelete/RevDelRevisionList.php
index 0705503e9bec..1eaf0cc96c89 100644
--- a/includes/revisiondelete/RevDelRevisionList.php
+++ b/includes/revisiondelete/RevDelRevisionList.php
@@ -19,6 +19,7 @@
* @ingroup RevisionDelete
*/
+use MediaWiki\MediaWikiServices;
use MediaWiki\Storage\RevisionRecord;
use Wikimedia\Rdbms\FakeResultWrapper;
use Wikimedia\Rdbms\IDatabase;
@@ -177,9 +178,10 @@ class RevDelRevisionList extends RevDelList {
}
public function doPostCommitUpdates( array $visibilityChangeMap ) {
- $this->title->purgeSquid();
+ MediaWikiServices::getInstance()->getHtmlCacheUpdater()->purge( $this->title );
// Extensions that require referencing previous revisions may need this
- Hooks::run( 'ArticleRevisionVisibilitySet', [ $this->title, $this->ids, $visibilityChangeMap ] );
+ Hooks::run( 'ArticleRevisionVisibilitySet',
+ [ $this->title, $this->ids, $visibilityChangeMap ] );
return Status::newGood();
}
}