Example #1
0
 /**
  * Pop a job off of the queue.
  * This requires $wgJobClasses to be set for the given job type.
  * Outside callers should use JobQueueGroup::pop() instead of this function.
  *
  * @throws MWException
  * @return Job|bool Returns false if there are no jobs
  */
 public final function pop()
 {
     global $wgJobClasses;
     $this->assertNotReadOnly();
     if ($this->wiki !== wfWikiID()) {
         throw new MWException("Cannot pop '{$this->type}' job off foreign wiki queue.");
     } elseif (!isset($wgJobClasses[$this->type])) {
         // Do not pop jobs if there is no class for the queue type
         throw new MWException("Unrecognized job type '{$this->type}'.");
     }
     $job = $this->doPop();
     if (!$job) {
         $this->aggr->notifyQueueEmpty($this->wiki, $this->type);
     }
     // Flag this job as an old duplicate based on its "root" job...
     try {
         if ($job && $this->isRootJobOldDuplicate($job)) {
             JobQueue::incrStats('dupe_pops', $this->type);
             $job = DuplicateJob::newFromJob($job);
             // convert to a no-op
         }
     } catch (Exception $e) {
         // don't lose jobs over this
     }
     return $job;
 }
Example #2
0
 /**
  * Pop a job off of the queue.
  * This requires $wgJobClasses to be set for the given job type.
  * Outside callers should use JobQueueGroup::pop() instead of this function.
  *
  * @throws MWException
  * @return Job|bool Returns false if there are no jobs
  */
 public final function pop()
 {
     global $wgJobClasses;
     if ($this->wiki !== wfWikiID()) {
         throw new MWException("Cannot pop '{$this->type}' job off foreign wiki queue.");
     } elseif (!isset($wgJobClasses[$this->type])) {
         // Do not pop jobs if there is no class for the queue type
         throw new MWException("Unrecognized job type '{$this->type}'.");
     }
     wfProfileIn(__METHOD__);
     $job = $this->doPop();
     wfProfileOut(__METHOD__);
     // Flag this job as an old duplicate based on its "root" job...
     try {
         if ($job && $this->isRootJobOldDuplicate($job)) {
             JobQueue::incrStats('job-pop-duplicate', $this->type, 1, $this->wiki);
             $job = DuplicateJob::newFromJob($job);
             // convert to a no-op
         }
     } catch (MWException $e) {
         // don't lose jobs over this
     }
     return $job;
 }
 /**
  * @see JobQueue::doPop()
  * @return Job|bool
  */
 protected function doPop()
 {
     global $wgMemc;
     if ($wgMemc->get($this->getCacheKey('empty')) === 'true') {
         return false;
         // queue is empty
     }
     list($dbw, $scope) = $this->getMasterDB();
     $dbw->commit(__METHOD__, 'flush');
     // flush existing transaction
     $autoTrx = $dbw->getFlag(DBO_TRX);
     // get current setting
     $dbw->clearFlag(DBO_TRX);
     // make each query its own transaction
     $scopedReset = new ScopedCallback(function () use($dbw, $autoTrx) {
         $dbw->setFlag($autoTrx ? DBO_TRX : 0);
         // restore old setting
     });
     $uuid = wfRandomString(32);
     // pop attempt
     $job = false;
     // job popped off
     do {
         // retry when our row is invalid or deleted as a duplicate
         // Try to reserve a row in the DB...
         if (in_array($this->order, array('fifo', 'timestamp'))) {
             $row = $this->claimOldest($uuid);
         } else {
             // random first
             $rand = mt_rand(0, self::MAX_JOB_RANDOM);
             // encourage concurrent UPDATEs
             $gte = (bool) mt_rand(0, 1);
             // find rows with rand before/after $rand
             $row = $this->claimRandom($uuid, $rand, $gte);
         }
         // Check if we found a row to reserve...
         if (!$row) {
             $wgMemc->set($this->getCacheKey('empty'), 'true', self::CACHE_TTL_LONG);
             break;
             // nothing to do
         }
         wfIncrStats('job-pop');
         // Get the job object from the row...
         $title = Title::makeTitleSafe($row->job_namespace, $row->job_title);
         if (!$title) {
             $dbw->delete('job', array('job_id' => $row->job_id), __METHOD__);
             wfDebugLog('JobQueueDB', "Row has invalid title '{$row->job_title}'.");
             continue;
             // try again
         }
         $job = Job::factory($row->job_cmd, $title, self::extractBlob($row->job_params), $row->job_id);
         $job->id = $row->job_id;
         // XXX: work around broken subclasses
         // Flag this job as an old duplicate based on its "root" job...
         if ($this->isRootJobOldDuplicate($job)) {
             wfIncrStats('job-pop-duplicate');
             $job = DuplicateJob::newFromJob($job);
             // convert to a no-op
         }
         break;
         // done
     } while (true);
     return $job;
 }