summaryrefslogtreecommitdiff
path: root/includes/jobqueue/jobs
diff options
context:
space:
mode:
Diffstat (limited to 'includes/jobqueue/jobs')
-rw-r--r--includes/jobqueue/jobs/ActivityUpdateJob.php75
-rw-r--r--includes/jobqueue/jobs/AssembleUploadChunksJob.php2
-rw-r--r--includes/jobqueue/jobs/DoubleRedirectJob.php20
-rw-r--r--includes/jobqueue/jobs/DuplicateJob.php2
-rw-r--r--includes/jobqueue/jobs/EmaillingJob.php4
-rw-r--r--includes/jobqueue/jobs/EnotifNotifyJob.php2
-rw-r--r--includes/jobqueue/jobs/EnqueueJob.php21
-rw-r--r--includes/jobqueue/jobs/HTMLCacheUpdateJob.php2
-rw-r--r--includes/jobqueue/jobs/NullJob.php2
-rw-r--r--includes/jobqueue/jobs/PublishStashedFileJob.php2
-rw-r--r--includes/jobqueue/jobs/RecentChangesUpdateJob.php8
-rw-r--r--includes/jobqueue/jobs/RefreshLinksJob.php51
-rw-r--r--includes/jobqueue/jobs/ThumbnailRenderJob.php14
-rw-r--r--includes/jobqueue/jobs/UploadFromUrlJob.php6
14 files changed, 159 insertions, 52 deletions
diff --git a/includes/jobqueue/jobs/ActivityUpdateJob.php b/includes/jobqueue/jobs/ActivityUpdateJob.php
new file mode 100644
index 00000000..f146e6e8
--- /dev/null
+++ b/includes/jobqueue/jobs/ActivityUpdateJob.php
@@ -0,0 +1,75 @@
+<?php
+/**
+ * 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
+ * @author Aaron Schulz
+ * @ingroup JobQueue
+ */
+
+/**
+ * Job for updating user activity like "last viewed" timestamps
+ *
+ * @ingroup JobQueue
+ * @since 1.26
+ */
+class ActivityUpdateJob extends Job {
+ function __construct( Title $title, array $params ) {
+ parent::__construct( 'activityUpdateJob', $title, $params );
+
+ if ( !isset( $params['type'] ) ) {
+ throw new InvalidArgumentException( "Missing 'type' parameter." );
+ }
+
+ $this->removeDuplicates = true;
+ }
+
+ public function run() {
+ if ( $this->params['type'] === 'updateWatchlistNotification' ) {
+ $this->updateWatchlistNotification();
+ } else {
+ throw new Exception( "Invalid 'type' parameter '{$this->params['type']}'." );
+ }
+
+ return true;
+ }
+
+ protected function updateWatchlistNotification() {
+ $casTimestamp = ( $this->params['notifTime'] !== null )
+ ? $this->params['notifTime']
+ : $this->params['curTime'];
+
+ $dbw = wfGetDB( DB_MASTER );
+ $dbw->update( 'watchlist',
+ array(
+ 'wl_notificationtimestamp' => $dbw->timestampOrNull( $this->params['notifTime'] )
+ ),
+ array(
+ 'wl_user' => $this->params['userid'],
+ 'wl_namespace' => $this->title->getNamespace(),
+ 'wl_title' => $this->title->getDBkey(),
+ // Add a "check and set" style comparison to handle conflicts.
+ // The inequality always avoids updates when the current value
+ // is already NULL per ANSI SQL. This is desired since NULL means
+ // that the user is "caught up" on edits already. When the field
+ // is non-NULL, make sure not to set it back in time or set it to
+ // NULL when newer revisions were in fact added to the page.
+ 'wl_notificationtimestamp < ' . $dbw->addQuotes( $dbw->timestamp( $casTimestamp ) )
+ ),
+ __METHOD__
+ );
+ }
+}
diff --git a/includes/jobqueue/jobs/AssembleUploadChunksJob.php b/includes/jobqueue/jobs/AssembleUploadChunksJob.php
index b7f09e77..a1de77e6 100644
--- a/includes/jobqueue/jobs/AssembleUploadChunksJob.php
+++ b/includes/jobqueue/jobs/AssembleUploadChunksJob.php
@@ -27,7 +27,7 @@
* @ingroup Upload
*/
class AssembleUploadChunksJob extends Job {
- public function __construct( $title, $params ) {
+ public function __construct( Title $title, array $params ) {
parent::__construct( 'AssembleUploadChunks', $title, $params );
$this->removeDuplicates = true;
}
diff --git a/includes/jobqueue/jobs/DoubleRedirectJob.php b/includes/jobqueue/jobs/DoubleRedirectJob.php
index 2561f2f1..ab638967 100644
--- a/includes/jobqueue/jobs/DoubleRedirectJob.php
+++ b/includes/jobqueue/jobs/DoubleRedirectJob.php
@@ -41,6 +41,16 @@ class DoubleRedirectJob extends Job {
private static $user;
/**
+ * @param Title $title
+ * @param array $params
+ */
+ function __construct( Title $title, array $params ) {
+ parent::__construct( 'fixDoubleRedirect', $title, $params );
+ $this->reason = $params['reason'];
+ $this->redirTitle = Title::newFromText( $params['redirTitle'] );
+ }
+
+ /**
* Insert jobs into the job queue to fix redirects to the given title
* @param string $reason The reason for the fix, see message
* "double-redirect-fixed-<reason>"
@@ -82,16 +92,6 @@ class DoubleRedirectJob extends Job {
}
/**
- * @param Title $title
- * @param array|bool $params
- */
- function __construct( $title, $params = false ) {
- parent::__construct( 'fixDoubleRedirect', $title, $params );
- $this->reason = $params['reason'];
- $this->redirTitle = Title::newFromText( $params['redirTitle'] );
- }
-
- /**
* @return bool
*/
function run() {
diff --git a/includes/jobqueue/jobs/DuplicateJob.php b/includes/jobqueue/jobs/DuplicateJob.php
index c5e3a234..068d5319 100644
--- a/includes/jobqueue/jobs/DuplicateJob.php
+++ b/includes/jobqueue/jobs/DuplicateJob.php
@@ -33,7 +33,7 @@ final class DuplicateJob extends Job {
* @param Title $title
* @param array $params Job parameters
*/
- function __construct( $title, $params ) {
+ function __construct( Title $title, array $params ) {
parent::__construct( 'duplicate', $title, $params );
}
diff --git a/includes/jobqueue/jobs/EmaillingJob.php b/includes/jobqueue/jobs/EmaillingJob.php
index df8ae63e..beeb0673 100644
--- a/includes/jobqueue/jobs/EmaillingJob.php
+++ b/includes/jobqueue/jobs/EmaillingJob.php
@@ -28,7 +28,7 @@
* @ingroup JobQueue
*/
class EmaillingJob extends Job {
- function __construct( $title, $params ) {
+ function __construct( Title $title = null, array $params ) {
parent::__construct( 'sendMail', Title::newMainPage(), $params );
}
@@ -38,7 +38,7 @@ class EmaillingJob extends Job {
$this->params['from'],
$this->params['subj'],
$this->params['body'],
- $this->params['replyto']
+ array( 'replyTo' => $this->params['replyto'] )
);
return $status->isOK();
diff --git a/includes/jobqueue/jobs/EnotifNotifyJob.php b/includes/jobqueue/jobs/EnotifNotifyJob.php
index 1ed99a58..9a5c3c72 100644
--- a/includes/jobqueue/jobs/EnotifNotifyJob.php
+++ b/includes/jobqueue/jobs/EnotifNotifyJob.php
@@ -27,7 +27,7 @@
* @ingroup JobQueue
*/
class EnotifNotifyJob extends Job {
- function __construct( $title, $params ) {
+ function __construct( Title $title, array $params ) {
parent::__construct( 'enotifNotify', $title, $params );
}
diff --git a/includes/jobqueue/jobs/EnqueueJob.php b/includes/jobqueue/jobs/EnqueueJob.php
index 46fb2aa7..c7ee9b65 100644
--- a/includes/jobqueue/jobs/EnqueueJob.php
+++ b/includes/jobqueue/jobs/EnqueueJob.php
@@ -40,13 +40,13 @@ final class EnqueueJob extends Job {
* @param Title $title
* @param array $params Job parameters
*/
- function __construct( $title, $params ) {
+ function __construct( Title $title, array $params ) {
parent::__construct( 'enqueue', $title, $params );
}
/**
- * @param Job|JobSpecification|array $jobs
- * @return JobRouteJob
+ * @param JobSpecification|JobSpecification[] $jobs
+ * @return EnqueueJob
*/
public static function newFromLocalJobs( $jobs ) {
$jobs = is_array( $jobs ) ? $jobs : array( $jobs );
@@ -56,9 +56,11 @@ final class EnqueueJob extends Job {
/**
* @param array $jobsByWiki Map of (wiki => JobSpecification list)
- * @return JobRouteJob
+ * @return EnqueueJob
*/
public static function newFromJobsByWiki( array $jobsByWiki ) {
+ $deduplicate = true;
+
$jobMapsByWiki = array();
foreach ( $jobsByWiki as $wiki => $jobs ) {
$jobMapsByWiki[$wiki] = array();
@@ -68,10 +70,19 @@ final class EnqueueJob extends Job {
} else {
throw new InvalidArgumentException( "Jobs must be of type JobSpecification." );
}
+ $deduplicate = $deduplicate && $job->ignoreDuplicates();
}
}
- return new self( Title::newMainPage(), array( 'jobsByWiki' => $jobMapsByWiki ) );
+ $eJob = new self(
+ Title::makeTitle( NS_SPECIAL, 'Badtitle/' . __CLASS__ ),
+ array( 'jobsByWiki' => $jobMapsByWiki )
+ );
+ // If *all* jobs to be pushed are to be de-duplicated (a common case), then
+ // de-duplicate this whole job itself to avoid build up in high traffic cases
+ $eJob->removeDuplicates = $deduplicate;
+
+ return $eJob;
}
public function run() {
diff --git a/includes/jobqueue/jobs/HTMLCacheUpdateJob.php b/includes/jobqueue/jobs/HTMLCacheUpdateJob.php
index e5e521c3..a9010c25 100644
--- a/includes/jobqueue/jobs/HTMLCacheUpdateJob.php
+++ b/includes/jobqueue/jobs/HTMLCacheUpdateJob.php
@@ -34,7 +34,7 @@
* @ingroup JobQueue
*/
class HTMLCacheUpdateJob extends Job {
- function __construct( $title, $params = '' ) {
+ function __construct( Title $title, array $params ) {
parent::__construct( 'htmlCacheUpdate', $title, $params );
// Base backlink purge jobs can be de-duplicated
$this->removeDuplicates = ( !isset( $params['range'] ) && !isset( $params['pages'] ) );
diff --git a/includes/jobqueue/jobs/NullJob.php b/includes/jobqueue/jobs/NullJob.php
index f94d6ebc..26d3c5c8 100644
--- a/includes/jobqueue/jobs/NullJob.php
+++ b/includes/jobqueue/jobs/NullJob.php
@@ -49,7 +49,7 @@ class NullJob extends Job {
* @param Title $title
* @param array $params Job parameters (lives, usleep)
*/
- function __construct( $title, $params ) {
+ function __construct( Title $title, array $params ) {
parent::__construct( 'null', $title, $params );
if ( !isset( $this->params['lives'] ) ) {
$this->params['lives'] = 1;
diff --git a/includes/jobqueue/jobs/PublishStashedFileJob.php b/includes/jobqueue/jobs/PublishStashedFileJob.php
index a922dd3d..8a180ec3 100644
--- a/includes/jobqueue/jobs/PublishStashedFileJob.php
+++ b/includes/jobqueue/jobs/PublishStashedFileJob.php
@@ -29,7 +29,7 @@
* @ingroup JobQueue
*/
class PublishStashedFileJob extends Job {
- public function __construct( $title, $params ) {
+ public function __construct( Title $title, array $params ) {
parent::__construct( 'PublishStashedFile', $title, $params );
$this->removeDuplicates = true;
}
diff --git a/includes/jobqueue/jobs/RecentChangesUpdateJob.php b/includes/jobqueue/jobs/RecentChangesUpdateJob.php
index cc04595d..d6fa26b8 100644
--- a/includes/jobqueue/jobs/RecentChangesUpdateJob.php
+++ b/includes/jobqueue/jobs/RecentChangesUpdateJob.php
@@ -27,7 +27,7 @@
* @since 1.25
*/
class RecentChangesUpdateJob extends Job {
- function __construct( $title, $params ) {
+ function __construct( Title $title, array $params ) {
parent::__construct( 'recentChangesUpdate', $title, $params );
if ( !isset( $params['type'] ) ) {
@@ -75,11 +75,13 @@ class RecentChangesUpdateJob extends Job {
$lockKey = wfWikiID() . ':recentchanges-prune';
$dbw = wfGetDB( DB_MASTER );
- if ( !$dbw->lock( $lockKey, __METHOD__, 1 ) ) {
+ if ( !$dbw->lockIsFree( $lockKey, __METHOD__ )
+ || !$dbw->lock( $lockKey, __METHOD__, 1 )
+ ) {
return; // already in progress
}
- $batchSize = 100; // Avoid slave lag
+ $batchSize = 100; // avoid slave lag
$cutoff = $dbw->timestamp( time() - $wgRCMaxAge );
do {
$rcIds = $dbw->selectFieldValues( 'recentchanges',
diff --git a/includes/jobqueue/jobs/RefreshLinksJob.php b/includes/jobqueue/jobs/RefreshLinksJob.php
index 1252b0b5..935d2fb1 100644
--- a/includes/jobqueue/jobs/RefreshLinksJob.php
+++ b/includes/jobqueue/jobs/RefreshLinksJob.php
@@ -37,7 +37,9 @@
class RefreshLinksJob extends Job {
const PARSE_THRESHOLD_SEC = 1.0;
- function __construct( $title, $params = '' ) {
+ const CLOCK_FUDGE = 10;
+
+ function __construct( Title $title, array $params ) {
parent::__construct( 'refreshLinks', $title, $params );
// A separate type is used just for cascade-protected backlinks
if ( !empty( $this->params['prioritize'] ) ) {
@@ -109,9 +111,6 @@ class RefreshLinksJob extends Job {
* @return bool
*/
protected function runForTitle( Title $title = null ) {
- $linkCache = LinkCache::singleton();
- $linkCache->clear();
-
if ( is_null( $title ) ) {
$this->setLastError( "refreshLinks: Invalid title" );
return false;
@@ -124,14 +123,18 @@ class RefreshLinksJob extends Job {
wfGetLB()->waitFor( $this->params['masterPos'] );
}
- $page = WikiPage::factory( $title );
+ // Clear out title cache data from prior job transaction snapshots
+ $linkCache = LinkCache::singleton();
+ $linkCache->clear();
- // Fetch the current revision...
+ // Fetch the current page and revision...
+ $page = WikiPage::factory( $title );
$revision = Revision::newFromTitle( $title, false, Revision::READ_NORMAL );
if ( !$revision ) {
$this->setLastError( "refreshLinks: Article not found {$title->getPrefixedDBkey()}" );
return false; // XXX: what if it was just deleted?
}
+
$content = $revision->getContent( Revision::RAW );
if ( !$content ) {
// If there is no content, pretend the content is empty
@@ -140,34 +143,50 @@ class RefreshLinksJob extends Job {
$parserOutput = false;
$parserOptions = $page->makeParserOptions( 'canonical' );
- // If page_touched changed after this root job (with a good slave lag skew factor),
- // then it is likely that any views of the pages already resulted in re-parses which
- // are now in cache. This can be reused to avoid expensive parsing in some cases.
+ // If page_touched changed after this root job, then it is likely that
+ // any views of the pages already resulted in re-parses which are now in
+ // cache. The cache can be reused to avoid expensive parsing in some cases.
if ( isset( $this->params['rootJobTimestamp'] ) ) {
- $skewedTimestamp = wfTimestamp( TS_UNIX, $this->params['rootJobTimestamp'] ) + 5;
- if ( $page->getLinksTimestamp() > wfTimestamp( TS_MW, $skewedTimestamp ) ) {
+ $opportunistic = !empty( $this->params['isOpportunistic'] );
+
+ $skewedTimestamp = $this->params['rootJobTimestamp'];
+ if ( $opportunistic ) {
+ // Neither clock skew nor DB snapshot/slave lag matter much for such
+ // updates; focus on reusing the (often recently updated) cache
+ } else {
+ // For transclusion updates, the template changes must be reflected
+ $skewedTimestamp = wfTimestamp( TS_MW,
+ wfTimestamp( TS_UNIX, $skewedTimestamp ) + self::CLOCK_FUDGE
+ );
+ }
+
+ if ( $page->getLinksTimestamp() > $skewedTimestamp ) {
// Something already updated the backlinks since this job was made
return true;
}
- if ( $page->getTouched() > wfTimestamp( TS_MW, $skewedTimestamp ) ) {
+
+ if ( $page->getTouched() >= $skewedTimestamp || $opportunistic ) {
+ // Something bumped page_touched since this job was made
+ // or the cache is otherwise suspected to be up-to-date
$parserOutput = ParserCache::singleton()->getDirty( $page, $parserOptions );
- if ( $parserOutput && $parserOutput->getCacheTime() <= $skewedTimestamp ) {
+ if ( $parserOutput && $parserOutput->getCacheTime() < $skewedTimestamp ) {
$parserOutput = false; // too stale
}
}
}
+
// Fetch the current revision and parse it if necessary...
if ( $parserOutput == false ) {
$start = microtime( true );
// Revision ID must be passed to the parser output to get revision variables correct
$parserOutput = $content->getParserOutput(
$title, $revision->getId(), $parserOptions, false );
- $ellapsed = microtime( true ) - $start;
+ $elapsed = microtime( true ) - $start;
// If it took a long time to render, then save this back to the cache to avoid
// wasted CPU by other apaches or job runners. We don't want to always save to
// cache as this can cause high cache I/O and LRU churn when a template changes.
- if ( $ellapsed >= self::PARSE_THRESHOLD_SEC
- && $page->isParserCacheUsed( $parserOptions, $revision->getId() )
+ if ( $elapsed >= self::PARSE_THRESHOLD_SEC
+ && $page->shouldCheckParserCache( $parserOptions, $revision->getId() )
&& $parserOutput->isCacheable()
) {
$ctime = wfTimestamp( TS_MW, (int)$start ); // cache time
diff --git a/includes/jobqueue/jobs/ThumbnailRenderJob.php b/includes/jobqueue/jobs/ThumbnailRenderJob.php
index ab381388..f558c488 100644
--- a/includes/jobqueue/jobs/ThumbnailRenderJob.php
+++ b/includes/jobqueue/jobs/ThumbnailRenderJob.php
@@ -27,7 +27,7 @@
* @ingroup JobQueue
*/
class ThumbnailRenderJob extends Job {
- public function __construct( $title, $params ) {
+ public function __construct( Title $title, array $params ) {
parent::__construct( 'ThumbnailRender', $title, $params );
}
@@ -50,16 +50,16 @@ class ThumbnailRenderJob extends Job {
return false;
}
} elseif ( $wgUploadThumbnailRenderMethod === 'http' ) {
- $status = $this->hitThumbUrl( $file, $transformParams );
+ $thumbUrl = '';
+ $status = $this->hitThumbUrl( $file, $transformParams, $thumbUrl );
wfDebug( __METHOD__ . ": received status {$status}\n" );
- if ( $status === 200 || $status === 301 || $status === 302 ) {
+ // 400 happens when requesting a size greater or equal than the original
+ if ( $status === 200 || $status === 301 || $status === 302 || $status === 400 ) {
return true;
} elseif ( $status ) {
- // Note that this currently happens (500) when requesting sizes larger then or
- // equal to the original, which is harmless.
- $this->setLastError( __METHOD__ . ': incorrect HTTP status ' . $status );
+ $this->setLastError( __METHOD__ . ': incorrect HTTP status ' . $status . ' when hitting ' . $thumbUrl );
return false;
} else {
$this->setLastError( __METHOD__ . ': HTTP request failure' );
@@ -75,7 +75,7 @@ class ThumbnailRenderJob extends Job {
}
}
- protected function hitThumbUrl( $file, $transformParams ) {
+ protected function hitThumbUrl( $file, $transformParams, &$thumbUrl ) {
global $wgUploadThumbnailRenderHttpCustomHost, $wgUploadThumbnailRenderHttpCustomDomain;
$thumbName = $file->thumbName( $transformParams );
diff --git a/includes/jobqueue/jobs/UploadFromUrlJob.php b/includes/jobqueue/jobs/UploadFromUrlJob.php
index d15fd025..ade48106 100644
--- a/includes/jobqueue/jobs/UploadFromUrlJob.php
+++ b/includes/jobqueue/jobs/UploadFromUrlJob.php
@@ -39,7 +39,7 @@ class UploadFromUrlJob extends Job {
/** @var User */
protected $user;
- public function __construct( $title, $params ) {
+ public function __construct( Title $title, array $params ) {
parent::__construct( 'uploadFromUrl', $title, $params );
}
@@ -166,11 +166,11 @@ class UploadFromUrlJob extends Job {
}
/**
- * Initialize the session data. Sets the intial result to queued.
+ * Initialize the session data. Sets the initial result to queued.
*/
public function initializeSessionData() {
$session =& self::getSessionData( $this->params['sessionKey'] );
- $$session['result'] = 'Queued';
+ $session['result'] = 'Queued';
}
/**