Merge "Make registerTempTableOperation() detect TRUNCATE operations"
[lhc/web/wiklou.git] / includes / jobqueue / Job.php
index 9ccf6f8..703e485 100644 (file)
@@ -69,12 +69,22 @@ abstract class Job implements IJobSpecification {
                global $wgJobClasses;
 
                if ( isset( $wgJobClasses[$command] ) ) {
-                       $class = $wgJobClasses[$command];
-
-                       $job = new $class( $title, $params );
-                       $job->command = $command;
+                       $handler = $wgJobClasses[$command];
+
+                       if ( is_callable( $handler ) ) {
+                               $job = call_user_func( $handler, $title, $params );
+                       } elseif ( class_exists( $handler ) ) {
+                               $job = new $handler( $title, $params );
+                       } else {
+                               $job = null;
+                       }
 
-                       return $job;
+                       if ( $job instanceof Job ) {
+                               $job->command = $command;
+                               return $job;
+                       } else {
+                               throw new InvalidArgumentException( "Cannot instantiate job '$command': bad spec!" );
+                       }
                }
 
                throw new InvalidArgumentException( "Invalid job command '{$command}'" );
@@ -92,6 +102,10 @@ abstract class Job implements IJobSpecification {
 
                // expensive jobs may set this to true
                $this->removeDuplicates = false;
+
+               if ( !isset( $this->params['requestId'] ) ) {
+                       $this->params['requestId'] = WebRequest::getRequestId();
+               }
        }
 
        /**
@@ -152,6 +166,18 @@ abstract class Job implements IJobSpecification {
                        : null;
        }
 
+       /**
+        * @return string|null Id of the request that created this job. Follows
+        *  jobs recursively, allowing to track the id of the request that started a
+        *  job when jobs insert jobs which insert other jobs.
+        * @since 1.27
+        */
+       public function getRequestId() {
+               return isset( $this->params['requestId'] )
+                       ? $this->params['requestId']
+                       : null;
+       }
+
        /**
         * @return int|null UNIX timestamp of when the job was runnable, or null
         * @since 1.26
@@ -214,6 +240,8 @@ abstract class Job implements IJobSpecification {
                        unset( $info['params']['rootJobTimestamp'] );
                        // Likewise for jobs with different delay times
                        unset( $info['params']['jobReleaseTimestamp'] );
+                       // Identical jobs from different requests should count as duplicates
+                       unset( $info['params']['requestId'] );
                        // Queues pack and hash this array, so normalize the order
                        ksort( $info['params'] );
                }
@@ -283,7 +311,9 @@ abstract class Job implements IJobSpecification {
        }
 
        /**
-        * @param callable $callback
+        * @param callable $callback A function with one parameter, the success status, which will be
+        *   false if the job failed or it succeeded but the DB changes could not be committed or
+        *   any deferred updates threw an exception. (This parameter was added in 1.28.)
         * @since 1.27
         */
        protected function addTeardownCallback( $callback ) {
@@ -292,12 +322,12 @@ abstract class Job implements IJobSpecification {
 
        /**
         * Do any final cleanup after run(), deferred updates, and all DB commits happen
-        *
+        * @param bool $status Whether the job, its deferred updates, and DB commit all succeeded
         * @since 1.27
         */
-       public function teardown() {
+       public function teardown( $status ) {
                foreach ( $this->teardownCallbacks as $callback ) {
-                       call_user_func( $callback );
+                       call_user_func( $callback, $status );
                }
        }