diff options
Diffstat (limited to 'maintenance/runJobs.php')
-rw-r--r-- | maintenance/runJobs.php | 122 |
1 files changed, 18 insertions, 104 deletions
diff --git a/maintenance/runJobs.php b/maintenance/runJobs.php index 429edf42..40605ceb 100644 --- a/maintenance/runJobs.php +++ b/maintenance/runJobs.php @@ -2,10 +2,6 @@ /** * Run pending jobs. * - * Options: - * --maxjobs <num> (default 10000) - * --type <job_cmd> - * * 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 @@ -40,19 +36,20 @@ class RunJobs extends Maintenance { $this->addOption( 'maxtime', 'Maximum amount of wall-clock time', false, true ); $this->addOption( 'type', 'Type of job to run', false, true ); $this->addOption( 'procs', 'Number of processes to use', false, true ); + $this->addOption( 'nothrottle', 'Ignore job throttling configuration', false, false ); + $this->addOption( 'result', 'Set to JSON to print only a JSON response', false, true ); } public function memoryLimit() { if ( $this->hasOption( 'memory-limit' ) ) { return parent::memoryLimit(); } + // Don't eat all memory on the machine if we get a bad job. return "150M"; } public function execute() { - global $wgTitle; - if ( wfReadOnly() ) { $this->error( "Unable to run jobs; the wiki is in read-only mode.", 1 ); // die } @@ -68,112 +65,29 @@ class RunJobs extends Maintenance { } } } - $maxJobs = $this->getOption( 'maxjobs', false ); - $maxTime = $this->getOption( 'maxtime', false ); - $startTime = time(); - $type = $this->getOption( 'type', false ); - $wgTitle = Title::newFromText( 'RunJobs.php' ); - $jobsRun = 0; // counter - - $group = JobQueueGroup::singleton(); - // Handle any required periodic queue maintenance - $count = $group->executeReadyPeriodicTasks(); - if ( $count > 0 ) { - $this->runJobsLog( "Executed $count periodic queue task(s)." ); - } - - $flags = JobQueueGroup::USE_CACHE | JobQueueGroup::USE_PRIORITY; - $lastTime = time(); // time since last slave check - do { - $job = ( $type === false ) - ? $group->pop( JobQueueGroup::TYPE_DEFAULT, $flags ) - : $group->pop( $type ); // job from a single queue - if ( $job ) { // found a job - ++$jobsRun; - $this->runJobsLog( $job->toString() . " STARTING" ); - - // Set timer to stop the job if too much CPU time is used - set_time_limit( $maxTime ?: 0 ); - // Run the job... - wfProfileIn( __METHOD__ . '-' . get_class( $job ) ); - $t = microtime( true ); - try { - $status = $job->run(); - $error = $job->getLastError(); - } catch ( MWException $e ) { - $status = false; - $error = get_class( $e ) . ': ' . $e->getMessage(); - $e->report(); // write error to STDERR and the log - } - $timeMs = intval( ( microtime( true ) - $t ) * 1000 ); - wfProfileOut( __METHOD__ . '-' . get_class( $job ) ); - // Disable the timer - set_time_limit( 0 ); - - // Mark the job as done on success or when the job cannot be retried - if ( $status !== false || !$job->allowRetries() ) { - $group->ack( $job ); // done - } - - if ( $status === false ) { - $this->runJobsLog( $job->toString() . " t=$timeMs error={$error}" ); - } else { - $this->runJobsLog( $job->toString() . " t=$timeMs good" ); - } - - // Break out if we hit the job count or wall time limits... - if ( $maxJobs && $jobsRun >= $maxJobs ) { - break; - } elseif ( $maxTime && ( time() - $startTime ) > $maxTime ) { - break; - } - // Don't let any of the main DB slaves get backed up - $timePassed = time() - $lastTime; - if ( $timePassed >= 5 || $timePassed < 0 ) { - wfWaitForSlaves(); - $lastTime = time(); - } - // Don't let any queue slaves/backups fall behind - if ( $jobsRun > 0 && ( $jobsRun % 100 ) == 0 ) { - $group->waitForBackups(); - } + $json = ( $this->getOption( 'result' ) === 'json' ); - // Bail if near-OOM instead of in a job - $this->assertMemoryOK(); - } - } while ( $job ); // stop when there are no jobs - } - - /** - * Make sure that this script is not too close to the memory usage limit - * @throws MWException - */ - private function assertMemoryOK() { - static $maxBytes = null; - if ( $maxBytes === null ) { - $m = array(); - if ( preg_match( '!^(\d+)(k|m|g|)$!i', ini_get( 'memory_limit' ), $m ) ) { - list( , $num, $unit ) = $m; - $conv = array( 'g' => 1024 * 1024 * 1024, 'm' => 1024 * 1024, 'k' => 1024, '' => 1 ); - $maxBytes = $num * $conv[strtolower( $unit )]; - } else { - $maxBytes = 0; - } + $runner = new JobRunner(); + if ( !$json ) { + $runner->setDebugHandler( array( $this, 'debugInternal' ) ); } - $usedBytes = memory_get_usage(); - if ( $maxBytes && $usedBytes >= 0.95 * $maxBytes ) { - throw new MWException( "Detected excessive memory usage ($usedBytes/$maxBytes)." ); + $response = $runner->run( array( + 'type' => $this->getOption( 'type', false ), + 'maxJobs' => $this->getOption( 'maxjobs', false ), + 'maxTime' => $this->getOption( 'maxtime', false ), + 'throttle' => $this->hasOption( 'nothrottle' ) ? false : true, + ) ); + if ( $json ) { + $this->output( FormatJson::encode( $response, true ) ); } } /** - * Log the job message - * @param $msg String The message to log + * @param string $s */ - private function runJobsLog( $msg ) { - $this->output( wfTimestamp( TS_DB ) . " $msg\n" ); - wfDebugLog( 'runJobs', $msg ); + public function debugInternal( $s ) { + $this->output( $s ); } } |