3 * Pick a database that has pending jobs
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * http://www.gnu.org/copyleft/gpl.html
21 * @todo Make this work on PostgreSQL and maybe other database servers
22 * @ingroup Maintenance
25 require_once( __DIR__
. '/Maintenance.php' );
28 * Maintenance script that picks a database that has pending jobs.
30 * @ingroup Maintenance
32 class nextJobDB
extends Maintenance
{
33 public function __construct() {
34 parent
::__construct();
35 $this->mDescription
= "Pick a database that has pending jobs";
36 $this->addOption( 'type', "The type of job to search for", false, true );
39 public function execute() {
42 $type = $this->getOption( 'type', false );
44 $memcKey = 'jobqueue:dbs:v3';
45 $pendingDbInfo = $wgMemc->get( $memcKey );
47 // If the cache entry wasn't present, or in 1% of cases otherwise,
48 // regenerate the cache. Use any available stale cache if another
49 // process is currently regenerating the pending DB information.
50 if ( !$pendingDbInfo ||
mt_rand( 0, 100 ) == 0 ) {
51 $lock = $wgMemc->add( 'jobqueue:dbs:v3:lock', 1, 1800 ); // lock
53 $pendingDbInfo = array(
54 'pendingDBs' => $this->getPendingDbs(),
57 $wgMemc->set( $memcKey, $pendingDbInfo );
58 $wgMemc->delete( 'jobqueue:dbs:v3:lock' ); // unlock
62 if ( !$pendingDbInfo ||
!$pendingDbInfo['pendingDBs'] ) {
63 return; // no DBs with jobs or cache is both empty and locked
65 $pendingDBs = $pendingDbInfo['pendingDBs'];
70 if ( $type === false ) {
71 $candidates = call_user_func_array( 'array_merge', $pendingDBs );
72 } elseif ( isset( $pendingDBs[$type] ) ) {
73 $candidates = $pendingDBs[$type];
75 $candidates = array();
81 $candidates = array_values( $candidates );
82 $db = $candidates[ mt_rand( 0, count( $candidates ) - 1 ) ];
83 if ( !$this->checkJob( $type, $db ) ) {
84 // This job is not available in the current database. Remove it from
86 if ( $type === false ) {
87 foreach ( $pendingDBs as $type2 => $dbs ) {
88 $pendingDBs[$type2] = array_diff( $pendingDBs[$type2], array( $db ) );
91 $pendingDBs[$type] = array_diff( $pendingDBs[$type], array( $db ) );
94 $wgMemc->set( $memcKey, $pendingDBs, 300 );
99 $this->output( $db . "\n" );
103 * Check if the specified database has a job of the specified type in it.
104 * The type may be false to indicate "all".
105 * @param $type string
106 * @param $dbName string
109 function checkJob( $type, $dbName ) {
110 $group = JobQueueGroup
::singleton( $dbName );
111 if ( $type === false ) {
112 foreach ( $group->getDefaultQueueTypes() as $type ) {
113 if ( !$group->get( $type )->isEmpty() ) {
119 return !$group->get( $type )->isEmpty();
124 * Get all databases that have a pending job
127 private function getPendingDbs() {
128 global $wgLocalDatabases;
130 $pendingDBs = array(); // (job type => (db list))
131 foreach ( $wgLocalDatabases as $db ) {
132 $types = JobQueueGroup
::singleton( $db )->getQueuesWithJobs();
133 foreach ( $types as $type ) {
134 $pendingDBs[$type][] = $db;
142 $maintClass = "nextJobDb";
143 require_once( RUN_MAINTENANCE_IF_MAIN
);