mw.Uri: Use more intuitive variable names
[lhc/web/wiklou.git] / includes / jobqueue / JobQueue.php
index 8cfed3b..f5ed7b9 100644 (file)
@@ -20,7 +20,7 @@
  * @file
  * @defgroup JobQueue JobQueue
  */
-use MediaWiki\MediaWikiServices;
+use Liuggio\StatsdClient\Factory\StatsdDataFactoryInterface;
 
 /**
  * Class to handle enqueueing and running of background jobs
@@ -41,6 +41,8 @@ abstract class JobQueue {
        protected $maxTries;
        /** @var string|bool Read only rationale (or false if r/w) */
        protected $readOnlyReason;
+       /** @var StatsdDataFactoryInterface */
+       protected $stats;
 
        /** @var BagOStuff */
        protected $dupCache;
@@ -66,8 +68,9 @@ abstract class JobQueue {
                if ( !in_array( $this->order, $this->supportedOrders() ) ) {
                        throw new JobQueueError( __CLASS__ . " does not support '{$this->order}' order." );
                }
-               $this->dupCache = wfGetCache( CACHE_ANYTHING );
                $this->readOnlyReason = $params['readOnlyReason'] ?? false;
+               $this->stats = $params['stats'] ?? new NullStatsdDataFactory();
+               $this->dupCache = $params['stash'] ?? new EmptyBagOStuff();
        }
 
        /**
@@ -91,6 +94,8 @@ abstract class JobQueue {
         *                  of jobs simply means re-inserting them into the queue. Jobs can be
         *                  attempted up to three times before being discarded.
         *   - readOnlyReason : Set this to a string to make the queue read-only.
+        *   - stash      : A BagOStuff instance that can be used for root job deduplication
+        *   - stats      : A StatsdDataFactoryInterface [optional]
         *
         * Queue classes should throw an exception if they do not support the options given.
         *
@@ -112,7 +117,7 @@ abstract class JobQueue {
        }
 
        /**
-        * @return string Wiki ID
+        * @return string Database domain ID
         */
        final public function getDomain() {
                return $this->domain;
@@ -356,26 +361,17 @@ abstract class JobQueue {
         * Outside callers should use JobQueueGroup::pop() instead of this function.
         *
         * @throws JobQueueError
-        * @return Job|bool Returns false if there are no jobs
+        * @return RunnableJob|bool Returns false if there are no jobs
         */
        final public function pop() {
-               global $wgJobClasses;
-
                $this->assertNotReadOnly();
-               if ( !WikiMap::isCurrentWikiDbDomain( $this->domain ) ) {
-                       throw new JobQueueError(
-                               "Cannot pop '{$this->type}' job off foreign '{$this->domain}' wiki queue." );
-               } elseif ( !isset( $wgJobClasses[$this->type] ) ) {
-                       // Do not pop jobs if there is no class for the queue type
-                       throw new JobQueueError( "Unrecognized job type '{$this->type}'." );
-               }
 
                $job = $this->doPop();
 
                // Flag this job as an old duplicate based on its "root" job...
                try {
                        if ( $job && $this->isRootJobOldDuplicate( $job ) ) {
-                               self::incrStats( 'dupe_pops', $this->type );
+                               $this->incrStats( 'dupe_pops', $this->type );
                                $job = DuplicateJob::newFromJob( $job ); // convert to a no-op
                        }
                } catch ( Exception $e ) {
@@ -387,7 +383,7 @@ abstract class JobQueue {
 
        /**
         * @see JobQueue::pop()
-        * @return Job|bool
+        * @return RunnableJob|bool
         */
        abstract protected function doPop();
 
@@ -397,11 +393,11 @@ abstract class JobQueue {
         * This does nothing for certain queue classes or if "claimTTL" is not set.
         * Outside callers should use JobQueueGroup::ack() instead of this function.
         *
-        * @param Job $job
+        * @param RunnableJob $job
         * @return void
         * @throws JobQueueError
         */
-       final public function ack( Job $job ) {
+       final public function ack( RunnableJob $job ) {
                $this->assertNotReadOnly();
                if ( $job->getType() !== $this->type ) {
                        throw new JobQueueError( "Got '{$job->getType()}' job; expected '{$this->type}'." );
@@ -412,9 +408,9 @@ abstract class JobQueue {
 
        /**
         * @see JobQueue::ack()
-        * @param Job $job
+        * @param RunnableJob $job
         */
-       abstract protected function doAck( Job $job );
+       abstract protected function doAck( RunnableJob $job );
 
        /**
         * Register the "root job" of a given job into the queue for de-duplication.
@@ -480,17 +476,17 @@ abstract class JobQueue {
                }
 
                // Update the timestamp of the last root job started at the location...
-               return $this->dupCache->set( $key, $params['rootJobTimestamp'], JobQueueDB::ROOTJOB_TTL );
+               return $this->dupCache->set( $key, $params['rootJobTimestamp'], self::ROOTJOB_TTL );
        }
 
        /**
         * Check if the "root" job of a given job has been superseded by a newer one
         *
-        * @param Job $job
+        * @param IJobSpecification $job
         * @throws JobQueueError
         * @return bool
         */
-       final protected function isRootJobOldDuplicate( Job $job ) {
+       final protected function isRootJobOldDuplicate( IJobSpecification $job ) {
                if ( $job->getType() !== $this->type ) {
                        throw new JobQueueError( "Got '{$job->getType()}' job; expected '{$this->type}'." );
                }
@@ -501,10 +497,10 @@ abstract class JobQueue {
 
        /**
         * @see JobQueue::isRootJobOldDuplicate()
-        * @param Job $job
+        * @param IJobSpecification $job
         * @return bool
         */
-       protected function doIsRootJobOldDuplicate( Job $job ) {
+       protected function doIsRootJobOldDuplicate( IJobSpecification $job ) {
                if ( !$job->hasRootJobParams() ) {
                        return false; // job has no de-deplication info
                }
@@ -690,6 +686,16 @@ abstract class JobQueue {
                return null; // not supported
        }
 
+       /**
+        * @param string $command
+        * @param array $params
+        * @return Job
+        */
+       protected function factoryJob( $command, $params ) {
+               // @TODO: dependency inject this as a callback
+               return Job::factory( $command, $params );
+       }
+
        /**
         * @throws JobQueueReadOnlyError
         */
@@ -707,12 +713,8 @@ abstract class JobQueue {
         * @param int $delta
         * @since 1.22
         */
-       public static function incrStats( $key, $type, $delta = 1 ) {
-               static $stats;
-               if ( !$stats ) {
-                       $stats = MediaWikiServices::getInstance()->getStatsdDataFactory();
-               }
-               $stats->updateCount( "jobqueue.{$key}.all", $delta );
-               $stats->updateCount( "jobqueue.{$key}.{$type}", $delta );
+       protected function incrStats( $key, $type, $delta = 1 ) {
+               $this->stats->updateCount( "jobqueue.{$key}.all", $delta );
+               $this->stats->updateCount( "jobqueue.{$key}.{$type}", $delta );
        }
 }