MediaWiki
REL1_22
|
00001 <?php 00024 require_once __DIR__ . '/Maintenance.php'; 00025 00031 class nextJobDB extends Maintenance { 00032 public function __construct() { 00033 parent::__construct(); 00034 $this->mDescription = "Pick a database that has pending jobs"; 00035 $this->addOption( 'type', "Search by job type", false, true ); 00036 $this->addOption( 'types', "Space separated list of job types to search for", false, true ); 00037 } 00038 00039 public function execute() { 00040 global $wgJobTypesExcludedFromDefaultQueue; 00041 00042 // job type required/picked 00043 if ( $this->hasOption( 'types' ) ) { 00044 $types = explode( ' ', $this->getOption( 'types' ) ); 00045 } elseif ( $this->hasOption( 'type' ) ) { 00046 $types = array( $this->getOption( 'type' ) ); 00047 } else { 00048 $types = false; 00049 } 00050 00051 // Handle any required periodic queue maintenance 00052 $this->executeReadyPeriodicTasks(); 00053 00054 // Get all the queues with jobs in them 00055 $pendingDBs = JobQueueAggregator::singleton()->getAllReadyWikiQueues(); 00056 if ( !count( $pendingDBs ) ) { 00057 return; // no DBs with jobs or cache is both empty and locked 00058 } 00059 00060 do { 00061 $again = false; 00062 00063 $candidates = array(); // list of (type, db) 00064 // Flatten the tree of candidates into a flat list so that a random 00065 // item can be selected, weighing each queue (type/db tuple) equally. 00066 foreach ( $pendingDBs as $type => $dbs ) { 00067 if ( 00068 ( is_array( $types ) && in_array( $type, $types ) ) || 00069 ( $types === false && !in_array( $type, $wgJobTypesExcludedFromDefaultQueue ) ) 00070 ) { 00071 foreach ( $dbs as $db ) { 00072 $candidates[] = array( $type, $db ); 00073 } 00074 } 00075 } 00076 if ( !count( $candidates ) ) { 00077 return; // no jobs for this type 00078 } 00079 00080 list( $type, $db ) = $candidates[mt_rand( 0, count( $candidates ) - 1 )]; 00081 if ( JobQueueGroup::singleton( $db )->isQueueDeprioritized( $type ) ) { 00082 $pendingDBs[$type] = array_diff( $pendingDBs[$type], array( $db ) ); 00083 $again = true; 00084 } 00085 } while ( $again ); 00086 00087 if ( $this->hasOption( 'types' ) ) { 00088 $this->output( $db . " " . $type . "\n" ); 00089 } else { 00090 $this->output( $db . "\n" ); 00091 } 00092 } 00093 00098 private function executeReadyPeriodicTasks() { 00099 global $wgLocalDatabases, $wgMemc; 00100 00101 $count = 0; 00102 $memcKey = 'jobqueue:periodic:lasttime'; 00103 $timestamp = (int)$wgMemc->get( $memcKey ); // UNIX timestamp or 0 00104 if ( ( time() - $timestamp ) > 300 || mt_rand( 0, 999 ) == 0 ) { // 5 minutes 00105 if ( $wgMemc->add( "$memcKey:rebuild", 1, 1800 ) ) { // lock 00106 foreach ( $wgLocalDatabases as $db ) { 00107 $count += JobQueueGroup::singleton( $db )->executeReadyPeriodicTasks(); 00108 } 00109 $wgMemc->set( $memcKey, time() ); 00110 $wgMemc->delete( "$memcKey:rebuild" ); // unlock 00111 } 00112 } 00113 00114 return $count; 00115 } 00116 } 00117 00118 $maintClass = "nextJobDb"; 00119 require_once RUN_MAINTENANCE_IF_MAIN;