) set.
* - b) Jobs to purge caches for a set of titles (the job title is ignored).
* These jobs have have (pages:(:(,),...) set.
*
* @ingroup JobQueue
*/
class HTMLCacheUpdateJob extends Job {
function __construct( $title, $params = '' ) {
parent::__construct( 'htmlCacheUpdate', $title, $params );
// Base backlink purge jobs can be de-duplicated
$this->removeDuplicates = ( !isset( $params['range'] ) && !isset( $params['pages'] ) );
}
function run() {
global $wgUpdateRowsPerJob, $wgUpdateRowsPerQuery, $wgMaxBacklinksInvalidate;
static $expected = array( 'recursive', 'pages' ); // new jobs have one of these
$oldRangeJob = false;
if ( !array_intersect( array_keys( $this->params ), $expected ) ) {
// B/C for older job params formats that lack these fields:
// a) base jobs with just ("table") and b) range jobs with ("table","start","end")
if ( isset( $this->params['start'] ) && isset( $this->params['end'] ) ) {
$oldRangeJob = true;
} else {
$this->params['recursive'] = true; // base job
}
}
// Job to purge all (or a range of) backlink pages for a page
if ( !empty( $this->params['recursive'] ) ) {
// @TODO: try to use delayed jobs if possible?
if ( !isset( $this->params['range'] ) && $wgMaxBacklinksInvalidate !== false ) {
$numRows = $this->title->getBacklinkCache()->getNumLinks(
$this->params['table'], $wgMaxBacklinksInvalidate );
if ( $numRows > $wgMaxBacklinksInvalidate ) {
return true;
}
}
// Convert this into no more than $wgUpdateRowsPerJob HTMLCacheUpdateJob per-title
// jobs and possibly a recursive HTMLCacheUpdateJob job for the rest of the backlinks
$jobs = BacklinkJobUtils::partitionBacklinkJob(
$this,
$wgUpdateRowsPerJob,
$wgUpdateRowsPerQuery, // jobs-per-title
// Carry over information for de-duplication
array( 'params' => $this->getRootJobParams() )
);
JobQueueGroup::singleton()->push( $jobs );
// Job to purge pages for for a set of titles
} elseif ( isset( $this->params['pages'] ) ) {
$this->invalidateTitles( $this->params['pages'] );
// B/C for job to purge a range of backlink pages for a given page
} elseif ( $oldRangeJob ) {
$titleArray = $this->title->getBacklinkCache()->getLinks(
$this->params['table'], $this->params['start'], $this->params['end'] );
$pages = array(); // same format BacklinkJobUtils uses
foreach ( $titleArray as $tl ) {
$pages[$tl->getArticleId()] = array( $tl->getNamespace(), $tl->getDbKey() );
}
$jobs = array();
foreach ( array_chunk( $pages, $wgUpdateRowsPerJob ) as $pageChunk ) {
$jobs[] = new HTMLCacheUpdateJob( $this->title,
array(
'table' => $this->params['table'],
'pages' => $pageChunk
) + $this->getRootJobParams() // carry over information for de-duplication
);
}
JobQueueGroup::singleton()->push( $jobs );
}
return true;
}
/**
* @param array $pages Map of (page ID => (namespace, DB key)) entries
*/
protected function invalidateTitles( array $pages ) {
global $wgUpdateRowsPerQuery, $wgUseFileCache, $wgUseSquid;
// Get all page IDs in this query into an array
$pageIds = array_keys( $pages );
if ( !$pageIds ) {
return;
}
$dbw = wfGetDB( DB_MASTER );
$timestamp = $dbw->timestamp();
// Don't invalidated pages that were already invalidated
$touchedCond = isset( $this->params['rootJobTimestamp'] )
? array( "page_touched < " .
$dbw->addQuotes( $dbw->timestamp( $this->params['rootJobTimestamp'] ) ) )
: array();
// Update page_touched (skipping pages already touched since the root job).
// Check $wgUpdateRowsPerQuery for sanity; batch jobs are sized by that already.
foreach ( array_chunk( $pageIds, $wgUpdateRowsPerQuery ) as $batch ) {
$dbw->update( 'page',
array( 'page_touched' => $timestamp ),
array( 'page_id' => $batch ) + $touchedCond,
__METHOD__
);
}
// Get the list of affected pages (races only mean something else did the purge)
$titleArray = TitleArray::newFromResult( $dbw->select(
'page',
array( 'page_namespace', 'page_title' ),
array( 'page_id' => $pageIds, 'page_touched' => $timestamp ),
__METHOD__
) );
// Update squid
if ( $wgUseSquid ) {
$u = SquidUpdate::newFromTitles( $titleArray );
$u->doUpdate();
}
// Update file cache
if ( $wgUseFileCache ) {
foreach ( $titleArray as $title ) {
HTMLFileCache::clearFileCache( $title );
}
}
}
public function workItemCount() {
return isset( $this->params['pages'] ) ? count( $this->params['pages'] ) : 1;
}
}