<?php
/**
- * Job queue base code
+ * Job queue base code.
+ *
+ * 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
* @defgroup JobQueue JobQueue
*/
-if ( !defined( 'MEDIAWIKI' ) ) {
- die( "This file is part of MediaWiki, it is not a valid entry point\n" );
-}
-
/**
* Class to both describe a background job and handle jobs.
*
$dbw = wfGetDB( DB_MASTER );
+ $dbw->begin( __METHOD__ );
+
$row = $dbw->selectRow(
'job',
'*',
array( 'job_cmd' => $type ),
__METHOD__,
- array( 'LIMIT' => 1 )
+ array( 'LIMIT' => 1, 'FOR UPDATE' )
);
if ( $row === false ) {
+ $dbw->commit( __METHOD__ );
wfProfileOut( __METHOD__ );
return false;
}
/* Ensure we "own" this row */
$dbw->delete( 'job', array( 'job_id' => $row->job_id ), __METHOD__ );
$affected = $dbw->affectedRows();
- $dbw->commit();
+ $dbw->commit( __METHOD__ );
if ( $affected == 0 ) {
wfProfileOut( __METHOD__ );
* @return Job or false if there's no jobs
*/
static function pop( $offset = 0 ) {
- global $wgJobTypesExcludedFromDefaultQueue;
wfProfileIn( __METHOD__ );
$dbr = wfGetDB( DB_SLAVE );
NB: If random fetch previously was used, offset
will always be ahead of few entries
*/
- $conditions = array();
- if ( count( $wgJobTypesExcludedFromDefaultQueue ) != 0 ) {
- foreach ( $wgJobTypesExcludedFromDefaultQueue as $cmdType ) {
- $conditions[] = "job_cmd != " . $dbr->addQuotes( $cmdType );
- }
- }
+
+ $conditions = self::defaultQueueConditions();
+
$offset = intval( $offset );
$options = array( 'ORDER BY' => 'job_id', 'USE INDEX' => 'PRIMARY' );
$dbw = wfGetDB( DB_MASTER );
$dbw->delete( 'job', array( 'job_id' => $row->job_id ), __METHOD__ );
$affected = $dbw->affectedRows();
- $dbw->commit();
+ $dbw->commit( __METHOD__ );
if ( !$affected ) {
// Failed, someone else beat us to it
// Delete the random row
$dbw->delete( 'job', array( 'job_id' => $row->job_id ), __METHOD__ );
$affected = $dbw->affectedRows();
- $dbw->commit();
+ $dbw->commit( __METHOD__ );
if ( !$affected ) {
// Random job gone before we exclusively deleted it
$namespace = $row->job_namespace;
$dbkey = $row->job_title;
$title = Title::makeTitleSafe( $namespace, $dbkey );
+
+ if ( is_null( $title ) ) {
+ wfProfileOut( __METHOD__ );
+ return false;
+ }
+
$job = Job::factory( $row->job_cmd, $title, Job::extractBlob( $row->job_params ), $row->job_id );
// Remove any duplicates it may have later in the queue
* @param $id Int: Job identifier
* @return Job
*/
- static function factory( $command, $title, $params = false, $id = 0 ) {
+ static function factory( $command, Title $title, $params = false, $id = 0 ) {
global $wgJobClasses;
if( isset( $wgJobClasses[$command] ) ) {
$class = $wgJobClasses[$command];
throw new MWException( "Invalid job command `{$command}`" );
}
+ /**
+ * @param $params
+ * @return string
+ */
static function makeBlob( $params ) {
if ( $params !== false ) {
return serialize( $params );
}
}
+ /**
+ * @param $blob
+ * @return bool|mixed
+ */
static function extractBlob( $blob ) {
if ( (string)$blob !== '' ) {
return unserialize( $blob );
}
$dbw = wfGetDB( DB_MASTER );
$rows = array();
+
+ /**
+ * @var $job Job
+ */
foreach ( $jobs as $job ) {
$rows[] = $job->insertFields();
if ( count( $rows ) >= 50 ) {
# Do a small transaction to avoid slave lag
- $dbw->begin();
+ $dbw->begin( __METHOD__ );
$dbw->insert( 'job', $rows, __METHOD__, 'IGNORE' );
- $dbw->commit();
+ $dbw->commit( __METHOD__ );
$rows = array();
}
}
if ( $rows ) { // last chunk
- $dbw->begin();
+ $dbw->begin( __METHOD__ );
$dbw->insert( 'job', $rows, __METHOD__, 'IGNORE' );
- $dbw->commit();
+ $dbw->commit( __METHOD__ );
}
wfIncrStats( 'job-insert', count( $jobs ) );
}
wfIncrStats( 'job-insert', count( $jobs ) );
}
+
+ /**
+ * SQL conditions to apply on most JobQueue queries
+ *
+ * Whenever we exclude jobs types from the default queue, we want to make
+ * sure that queries to the job queue actually ignore them.
+ *
+ * @return array SQL conditions suitable for Database:: methods
+ */
+ static function defaultQueueConditions( ) {
+ global $wgJobTypesExcludedFromDefaultQueue;
+ $conditions = array();
+ if ( count( $wgJobTypesExcludedFromDefaultQueue ) > 0 ) {
+ $dbr = wfGetDB( DB_SLAVE );
+ foreach ( $wgJobTypesExcludedFromDefaultQueue as $cmdType ) {
+ $conditions[] = "job_cmd != " . $dbr->addQuotes( $cmdType );
+ }
+ }
+ return $conditions;
+ }
+
/*-------------------------------------------------------------------------
* Non-static functions
*------------------------------------------------------------------------*/
if ( $this->removeDuplicates ) {
$res = $dbw->select( 'job', array( '1' ), $fields, __METHOD__ );
if ( $dbw->numRows( $res ) ) {
- return;
+ return true;
}
}
wfIncrStats( 'job-insert' );
return $dbw->insert( 'job', $fields, __METHOD__ );
}
+ /**
+ * @return array
+ */
protected function insertFields() {
$dbw = wfGetDB( DB_MASTER );
return array(
'job_cmd' => $this->command,
'job_namespace' => $this->title->getNamespace(),
'job_title' => $this->title->getDBkey(),
+ 'job_timestamp' => $dbw->timestamp(),
'job_params' => Job::makeBlob( $this->params )
);
}
$fields = $this->insertFields();
unset( $fields['job_id'] );
$dbw = wfGetDB( DB_MASTER );
- $dbw->begin();
+ $dbw->begin( __METHOD__ );
$dbw->delete( 'job', $fields, __METHOD__ );
$affected = $dbw->affectedRows();
- $dbw->commit();
+ $dbw->commit( __METHOD__ );
if ( $affected ) {
wfIncrStats( 'job-dup-delete', $affected );
}
}
+ /**
+ * @return string
+ */
function toString() {
$paramString = '';
if ( $this->params ) {