Change EnqueueJob docs to discourage obsolete use-cases
[lhc/web/wiklou.git] / includes / jobqueue / JobQueue.php
index 5b71938..1f4f179 100644 (file)
@@ -19,8 +19,8 @@
  *
  * @file
  * @defgroup JobQueue JobQueue
- * @author Aaron Schulz
  */
+use MediaWiki\MediaWikiServices;
 
 /**
  * Class to handle enqueueing and running of background jobs
 abstract class JobQueue {
        /** @var string Wiki ID */
        protected $wiki;
-
        /** @var string Job type */
        protected $type;
-
        /** @var string Job priority for pop() */
        protected $order;
-
        /** @var int Time to live in seconds */
        protected $claimTTL;
-
        /** @var int Maximum number of times to try a job */
        protected $maxTries;
+       /** @var string|bool Read only rationale (or false if r/w) */
+       protected $readOnlyReason;
 
        /** @var BagOStuff */
        protected $dupCache;
@@ -74,6 +72,9 @@ abstract class JobQueue {
                $this->aggr = isset( $params['aggregator'] )
                        ? $params['aggregator']
                        : new JobQueueAggregatorNull( [] );
+               $this->readOnlyReason = isset( $params['readOnlyReason'] )
+                       ? $params['readOnlyReason']
+                       : false;
        }
 
        /**
@@ -96,6 +97,7 @@ abstract class JobQueue {
         *                  but not acknowledged as completed after this many seconds. Recycling
         *                  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.
         *
         * Queue classes should throw an exception if they do not support the options given.
         *
@@ -168,6 +170,14 @@ abstract class JobQueue {
                return $this->supportsDelayedJobs();
        }
 
+       /**
+        * @return string|bool Read-only rational or false if r/w
+        * @since 1.27
+        */
+       public function getReadOnlyReason() {
+               return $this->readOnlyReason;
+       }
+
        /**
         * Quickly check if the queue has no available (unacquired, non-delayed) jobs.
         * Queue classes should use caching if they are any slower without memcached.
@@ -307,6 +317,8 @@ abstract class JobQueue {
         * @throws MWException
         */
        final public function batchPush( array $jobs, $flags = 0 ) {
+               $this->assertNotReadOnly();
+
                if ( !count( $jobs ) ) {
                        return; // nothing to do
                }
@@ -349,6 +361,7 @@ abstract class JobQueue {
        final public 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] ) ) {
@@ -365,7 +378,7 @@ abstract class JobQueue {
                // Flag this job as an old duplicate based on its "root" job...
                try {
                        if ( $job && $this->isRootJobOldDuplicate( $job ) ) {
-                               JobQueue::incrStats( 'dupe_pops', $this->type );
+                               self::incrStats( 'dupe_pops', $this->type );
                                $job = DuplicateJob::newFromJob( $job ); // convert to a no-op
                        }
                } catch ( Exception $e ) {
@@ -392,9 +405,11 @@ abstract class JobQueue {
         * @throws MWException
         */
        final public function ack( Job $job ) {
+               $this->assertNotReadOnly();
                if ( $job->getType() !== $this->type ) {
                        throw new MWException( "Got '{$job->getType()}' job; expected '{$this->type}'." );
                }
+
                $this->doAck( $job );
        }
 
@@ -436,12 +451,12 @@ abstract class JobQueue {
         * @return bool
         */
        final public function deduplicateRootJob( IJobSpecification $job ) {
+               $this->assertNotReadOnly();
                if ( $job->getType() !== $this->type ) {
                        throw new MWException( "Got '{$job->getType()}' job; expected '{$this->type}'." );
                }
-               $ok = $this->doDeduplicateRootJob( $job );
 
-               return $ok;
+               return $this->doDeduplicateRootJob( $job );
        }
 
        /**
@@ -524,6 +539,8 @@ abstract class JobQueue {
         * @return void
         */
        final public function delete() {
+               $this->assertNotReadOnly();
+
                $this->doDelete();
        }
 
@@ -536,7 +553,7 @@ abstract class JobQueue {
        }
 
        /**
-        * Wait for any slaves or backup servers to catch up.
+        * Wait for any replica DBs or backup servers to catch up.
         *
         * This does nothing for certain queue classes.
         *
@@ -672,6 +689,15 @@ abstract class JobQueue {
                return null; // not supported
        }
 
+       /**
+        * @throws JobQueueReadOnlyError
+        */
+       protected function assertNotReadOnly() {
+               if ( $this->readOnlyReason !== false ) {
+                       throw new JobQueueReadOnlyError( "Job queue is read-only: {$this->readOnlyReason}" );
+               }
+       }
+
        /**
         * Call wfIncrStats() for the queue overall and for the queue type
         *
@@ -683,7 +709,7 @@ abstract class JobQueue {
        public static function incrStats( $key, $type, $delta = 1 ) {
                static $stats;
                if ( !$stats ) {
-                       $stats = RequestContext::getMain()->getStats();
+                       $stats = MediaWikiServices::getInstance()->getStatsdDataFactory();
                }
                $stats->updateCount( "jobqueue.{$key}.all", $delta );
                $stats->updateCount( "jobqueue.{$key}.{$type}", $delta );
@@ -699,3 +725,7 @@ class JobQueueError extends MWException {
 
 class JobQueueConnectionError extends JobQueueError {
 }
+
+class JobQueueReadOnlyError extends JobQueueError {
+
+}