示例#1
0
 /**
  * Potentially open a socket and sent an HTTP request back to the server
  * to run a specified number of jobs. This registers a callback to cleanup
  * the socket once it's done.
  */
 protected function triggerJobs()
 {
     global $wgJobRunRate, $wgServer, $wgRunJobsAsync;
     if ($wgJobRunRate <= 0 || wfReadOnly()) {
         return;
     } elseif ($this->getTitle()->isSpecial('RunJobs')) {
         return;
         // recursion guard
     }
     $section = new ProfileSection(__METHOD__);
     if ($wgJobRunRate < 1) {
         $max = mt_getrandmax();
         if (mt_rand(0, $max) > $max * $wgJobRunRate) {
             return;
             // the higher $wgJobRunRate, the less likely we return here
         }
         $n = 1;
     } else {
         $n = intval($wgJobRunRate);
     }
     if (!$wgRunJobsAsync) {
         // If running jobs asynchronously has been disabled, run the job here
         // while the user waits
         SpecialRunJobs::executeJobs($n);
         return;
     }
     if (!JobQueueGroup::singleton()->queuesHaveJobs(JobQueueGroup::TYPE_DEFAULT)) {
         return;
         // do not send request if there are probably no jobs
     }
     $query = array('title' => 'Special:RunJobs', 'tasks' => 'jobs', 'maxjobs' => $n, 'sigexpiry' => time() + 5);
     $query['signature'] = SpecialRunJobs::getQuerySignature($query);
     $errno = $errstr = null;
     $info = wfParseUrl($wgServer);
     wfSuppressWarnings();
     $sock = fsockopen($info['host'], isset($info['port']) ? $info['port'] : 80, $errno, $errstr, 0.1);
     wfRestoreWarnings();
     if (!$sock) {
         wfDebugLog('runJobs', "Failed to start cron API (socket error {$errno}): {$errstr}\n");
         // Fall back to running the job here while the user waits
         SpecialRunJobs::executeJobs($n);
         return;
     }
     $url = wfAppendQuery(wfScript('index'), $query);
     $req = "POST {$url} HTTP/1.1\r\nHost: {$info['host']}\r\nConnection: Close\r\nContent-Length: 0\r\n\r\n";
     wfDebugLog('runJobs', "Running {$n} job(s) via '{$url}'\n");
     // Send a cron API request to be performed in the background.
     // Give up if this takes too long to send (which should be rare).
     stream_set_timeout($sock, 1);
     $bytes = fwrite($sock, $req);
     if ($bytes !== strlen($req)) {
         wfDebugLog('runJobs', "Failed to start cron API (socket write error)\n");
     } else {
         // Do not wait for the response (the script should handle client aborts).
         // Make sure that we don't close before that script reaches ignore_user_abort().
         $status = fgets($sock);
         if (!preg_match('#^HTTP/\\d\\.\\d 202 #', $status)) {
             wfDebugLog('runJobs', "Failed to start cron API: received '{$status}'\n");
         }
     }
     fclose($sock);
 }
示例#2
0
 /**
  * Potentially open a socket and sent an HTTP request back to the server
  * to run a specified number of jobs. This registers a callback to cleanup
  * the socket once it's done.
  */
 public function triggerJobs()
 {
     $jobRunRate = $this->config->get('JobRunRate');
     if ($this->getTitle()->isSpecial('RunJobs')) {
         return;
         // recursion guard
     } elseif ($jobRunRate <= 0 || wfReadOnly()) {
         return;
     }
     if ($jobRunRate < 1) {
         $max = mt_getrandmax();
         if (mt_rand(0, $max) > $max * $jobRunRate) {
             return;
             // the higher the job run rate, the less likely we return here
         }
         $n = 1;
     } else {
         $n = intval($jobRunRate);
     }
     $runJobsLogger = LoggerFactory::getInstance('runJobs');
     // Fall back to running the job(s) while the user waits if needed
     if (!$this->config->get('RunJobsAsync')) {
         $runner = new JobRunner($runJobsLogger);
         $runner->run(['maxJobs' => $n]);
         return;
     }
     // Do not send request if there are probably no jobs
     try {
         $group = JobQueueGroup::singleton();
         if (!$group->queuesHaveJobs(JobQueueGroup::TYPE_DEFAULT)) {
             return;
         }
     } catch (JobQueueError $e) {
         MWExceptionHandler::logException($e);
         return;
         // do not make the site unavailable
     }
     $query = ['title' => 'Special:RunJobs', 'tasks' => 'jobs', 'maxjobs' => $n, 'sigexpiry' => time() + 5];
     $query['signature'] = SpecialRunJobs::getQuerySignature($query, $this->config->get('SecretKey'));
     $errno = $errstr = null;
     $info = wfParseUrl($this->config->get('CanonicalServer'));
     $host = $info ? $info['host'] : null;
     $port = 80;
     if (isset($info['scheme']) && $info['scheme'] == 'https') {
         $host = "tls://" . $host;
         $port = 443;
     }
     if (isset($info['port'])) {
         $port = $info['port'];
     }
     MediaWiki\suppressWarnings();
     $sock = $host ? fsockopen($host, $port, $errno, $errstr, 0.1) : false;
     MediaWiki\restoreWarnings();
     $invokedWithSuccess = true;
     if ($sock) {
         $special = SpecialPageFactory::getPage('RunJobs');
         $url = $special->getPageTitle()->getCanonicalURL($query);
         $req = "POST {$url} HTTP/1.1\r\n" . "Host: {$info['host']}\r\n" . "Connection: Close\r\n" . "Content-Length: 0\r\n\r\n";
         $runJobsLogger->info("Running {$n} job(s) via '{$url}'");
         // Send a cron API request to be performed in the background.
         // Give up if this takes too long to send (which should be rare).
         stream_set_timeout($sock, 2);
         $bytes = fwrite($sock, $req);
         if ($bytes !== strlen($req)) {
             $invokedWithSuccess = false;
             $runJobsLogger->error("Failed to start cron API (socket write error)");
         } else {
             // Do not wait for the response (the script should handle client aborts).
             // Make sure that we don't close before that script reaches ignore_user_abort().
             $start = microtime(true);
             $status = fgets($sock);
             $sec = microtime(true) - $start;
             if (!preg_match('#^HTTP/\\d\\.\\d 202 #', $status)) {
                 $invokedWithSuccess = false;
                 $runJobsLogger->error("Failed to start cron API: received '{$status}' ({$sec})");
             }
         }
         fclose($sock);
     } else {
         $invokedWithSuccess = false;
         $runJobsLogger->error("Failed to start cron API (socket error {$errno}): {$errstr}");
     }
     // Fall back to running the job(s) while the user waits if needed
     if (!$invokedWithSuccess) {
         $runJobsLogger->warning("Jobs switched to blocking; Special:RunJobs disabled");
         $runner = new JobRunner($runJobsLogger);
         $runner->run(['maxJobs' => $n]);
     }
 }
示例#3
0
 /**
  * Potentially open a socket and sent an HTTP request back to the server
  * to run a specified number of jobs. This registers a callback to cleanup
  * the socket once it's done.
  */
 public function triggerJobs()
 {
     $jobRunRate = $this->config->get('JobRunRate');
     if ($jobRunRate <= 0 || wfReadOnly()) {
         return;
     } elseif ($this->getTitle()->isSpecial('RunJobs')) {
         return;
         // recursion guard
     }
     if ($jobRunRate < 1) {
         $max = mt_getrandmax();
         if (mt_rand(0, $max) > $max * $jobRunRate) {
             return;
             // the higher the job run rate, the less likely we return here
         }
         $n = 1;
     } else {
         $n = intval($jobRunRate);
     }
     $runJobsLogger = LoggerFactory::getInstance('runJobs');
     if (!$this->config->get('RunJobsAsync')) {
         // Fall back to running the job here while the user waits
         $runner = new JobRunner($runJobsLogger);
         $runner->run(array('maxJobs' => $n));
         return;
     }
     try {
         if (!JobQueueGroup::singleton()->queuesHaveJobs(JobQueueGroup::TYPE_DEFAULT)) {
             return;
             // do not send request if there are probably no jobs
         }
     } catch (JobQueueError $e) {
         MWExceptionHandler::logException($e);
         return;
         // do not make the site unavailable
     }
     $query = array('title' => 'Special:RunJobs', 'tasks' => 'jobs', 'maxjobs' => $n, 'sigexpiry' => time() + 5);
     $query['signature'] = SpecialRunJobs::getQuerySignature($query, $this->config->get('SecretKey'));
     $errno = $errstr = null;
     $info = wfParseUrl($this->config->get('Server'));
     MediaWiki\suppressWarnings();
     $sock = fsockopen($info['host'], isset($info['port']) ? $info['port'] : 80, $errno, $errstr, 0.1);
     MediaWiki\restoreWarnings();
     if (!$sock) {
         $runJobsLogger->error("Failed to start cron API (socket error {$errno}): {$errstr}");
         // Fall back to running the job here while the user waits
         $runner = new JobRunner($runJobsLogger);
         $runner->run(array('maxJobs' => $n));
         return;
     }
     $url = wfAppendQuery(wfScript('index'), $query);
     $req = "POST {$url} HTTP/1.1\r\n" . "Host: {$info['host']}\r\n" . "Connection: Close\r\n" . "Content-Length: 0\r\n\r\n";
     $runJobsLogger->info("Running {$n} job(s) via '{$url}'");
     // Send a cron API request to be performed in the background.
     // Give up if this takes too long to send (which should be rare).
     stream_set_timeout($sock, 1);
     $bytes = fwrite($sock, $req);
     if ($bytes !== strlen($req)) {
         $runJobsLogger->error("Failed to start cron API (socket write error)");
     } else {
         // Do not wait for the response (the script should handle client aborts).
         // Make sure that we don't close before that script reaches ignore_user_abort().
         $status = fgets($sock);
         if (!preg_match('#^HTTP/\\d\\.\\d 202 #', $status)) {
             $runJobsLogger->error("Failed to start cron API: received '{$status}'");
         }
     }
     fclose($sock);
 }