r83634 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r83633‎ | r83634 | r83635 >
Date:04:10, 10 March 2011
Author:tstarling
Status:ok
Tags:
Comment:
Rewrite the caching code in nextJobDB.php so that jobs-loop.sh has a chance of being able to exit from the "high-priority" loop.

The current syndrome is that when the cache expires, a small number of high-priority jobs are added. These jobs are quickly cleared, but the job runners do not continue on to other things, because the cache keeps returning the same small list of wikis for 5 minutes. After 5 minutes, there are a few more jobs in the high-priority list, so the cycle continues.
Modified paths:
  • /trunk/phase3/maintenance/nextJobDB.php (modified) (history)

Diff [purge]

Index: trunk/phase3/maintenance/nextJobDB.php
@@ -33,20 +33,71 @@
3434 public function execute() {
3535 global $wgMemc;
3636 $type = $this->getOption( 'type', false );
37 - $mckey = $type === false
38 - ? "jobqueue:dbs"
39 - : "jobqueue:dbs:$type";
40 - $pendingDBs = $wgMemc->get( $mckey );
4137
42 - # If we didn't get it from the cache
 38+ $memcKey = 'jobqueue:dbs:v2';
 39+ $pendingDBs = $wgMemc->get( $memcKey );
 40+
 41+ // If the cache entry wasn't present, or in 1% of cases otherwise,
 42+ // regenerate the cache.
 43+ if ( !$pendingDBs || mt_rand( 0, 100 ) == 0 ) {
 44+ $pendingDBs = $this->getPendingDbs();
 45+ $wgMemc->set( $memcKey, $pendingDBs, 300 );
 46+ }
 47+
4348 if ( !$pendingDBs ) {
44 - $pendingDBs = $this->getPendingDbs( $type );
45 - $wgMemc->set( $mckey, $pendingDBs, 300 );
 49+ return;
4650 }
47 - # If we've got a pending job in a db, display it.
48 - if ( $pendingDBs ) {
49 - $this->output( $pendingDBs[mt_rand( 0, count( $pendingDBs ) - 1 )] );
 51+
 52+ do {
 53+ $again = false;
 54+
 55+ if ( $type === false ) {
 56+ $candidates = call_user_func_array( 'array_merge', $pendingDBs );
 57+ } elseif ( isset( $pendingDBs[$type] ) ) {
 58+ $candidates = $pendingDBs[$type];
 59+ } else {
 60+ $candidates = array();
 61+ }
 62+ if ( !$candidates ) {
 63+ return;
 64+ }
 65+
 66+ $db = $candidates[ mt_rand( 0, count( $candidates ) - 1 ) ];
 67+ if ( !$this->checkJob( $type, $db ) ) {
 68+ // This job is not available in the current database. Remove it from
 69+ // the cache.
 70+ if ( $type === false ) {
 71+ foreach ( $pendingDBs as $type2 => $dbs ) {
 72+ $pendingDBs[$type2] = array_diff( $pendingDBs[$type2], array( $db ) );
 73+ }
 74+ } else {
 75+ $pendingDBs[$type] = array_diff( $pendingDBs[$type], array( $db ) );
 76+ }
 77+
 78+ $wgMemc->set( $memcKey, $pendingDBs, 300 );
 79+ $again = true;
 80+ }
 81+ } while ( $again );
 82+
 83+ $this->output( $db . "\n" );
 84+ }
 85+
 86+ /**
 87+ * Check if the specified database has a job of the specified type in it.
 88+ * The type may be false to indicate "all".
 89+ */
 90+ function checkJob( $type, $db ) {
 91+ $lb = wfGetLB( $db );
 92+ $db = $lb->getConnection( DB_MASTER );
 93+ if ( $type === false ) {
 94+ $conds = array();
 95+ } else {
 96+ $conds = array( 'job_cmd' => $type );
5097 }
 98+
 99+ $exists = (bool) $db->selectField( 'job', '1', $conds, __METHOD__ );
 100+ $lb->reuseConnection( $db );
 101+ return $exists;
51102 }
52103
53104 /**
@@ -54,7 +105,7 @@
55106 * @param $type String Job type
56107 * @return array
57108 */
58 - private function getPendingDbs( $type ) {
 109+ private function getPendingDbs() {
59110 global $wgLocalDatabases;
60111 $pendingDBs = array();
61112 # Cross-reference DBs by master DB server
@@ -66,10 +117,10 @@
67118
68119 foreach ( $dbsByMaster as $dbs ) {
69120 $dbConn = wfGetDB( DB_MASTER, array(), $dbs[0] );
70 - $stype = $dbConn->addQuotes( $type );
71121
72122 # Padding row for MySQL bug
73 - $sql = "(SELECT '-------------------------------------------' as db)";
 123+ $pad = str_repeat( '-', 40 );
 124+ $sql = "(SELECT '$pad' as db, '$pad' as job_cmd)";
74125 foreach ( $dbs as $wikiId ) {
75126 if ( $sql != '' ) {
76127 $sql .= ' UNION ';
@@ -79,10 +130,7 @@
80131 $dbConn->tablePrefix( $tablePrefix );
81132 $jobTable = $dbConn->tableName( 'job' );
82133
83 - if ( $type === false )
84 - $sql .= "(SELECT '$wikiId' as db FROM $dbName.$jobTable LIMIT 1)";
85 - else
86 - $sql .= "(SELECT '$wikiId' as db FROM $dbName.$jobTable WHERE job_cmd=$stype LIMIT 1)";
 134+ $sql .= "(SELECT DISTINCT '$wikiId' as db, job_cmd FROM $dbName.$jobTable GROUP BY job_cmd)";
87135 }
88136 $res = $dbConn->query( $sql, __METHOD__ );
89137 $first = true;
@@ -92,7 +140,7 @@
93141 $first = false;
94142 continue;
95143 }
96 - $pendingDBs[] = $row->db;
 144+ $pendingDBs[$row->job_cmd][] = $row->db;
97145 }
98146 }
99147 return $pendingDBs;

Follow-up revisions

RevisionCommit summaryAuthorDate
r83635MFT r83634: nextJobDB.php caching fix.tstarling04:12, 10 March 2011
r83636Some bug fixes for r83634.tstarling04:47, 10 March 2011

Status & tagging log