jenkins-bot has submitted this change and it was merged. ( 
https://gerrit.wikimedia.org/r/369999 )

Change subject: Create a lightweight JobRunner that just executes a job.
......................................................................


Create a lightweight JobRunner that just executes a job.

In the current JobQueue architecture the JobRunner is
responsible for both dequeueing and executing the jobs.
When moving to kafka-based implementation, ChangeProp
will handle the dequeueing part and post the jobs for
execution, so we need a lighter-weight version of the
JobRunner that just executes the job.

The JobExecutor is a bare-bone executor without any
stats reporting, transaction/replica lag management
or other features from the JobRunner. These features
will be added on demand. In future the JobExecutor
will be transfered to the core and the JobRunner will
delegate the actual execution to it, so all the code
duplication will be removed. However right now we need
to set up the whole pipeline to test whether the new
architecture works as a whole and see whether we need
any additional features from the JobRunner at all.

Change-Id: Ib1aaa58a730b20ee266a530150d684ae9782e6d2
---
A JobExecutor.php
M extension.json
2 files changed, 141 insertions(+), 1 deletion(-)

Approvals:
  Mobrovac: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/JobExecutor.php b/JobExecutor.php
new file mode 100644
index 0000000..3631c6d
--- /dev/null
+++ b/JobExecutor.php
@@ -0,0 +1,139 @@
+<?php
+
+/**
+ * Class JobExecutor.
+ *
+ * A massively simplified JobRunner with a solo purpose of
+ * executing a Job
+ */
+
+use MediaWiki\Logger\LoggerFactory;
+use MediaWiki\MediaWikiServices;
+use Psr\Log\LoggerInterface;
+
+class JobExecutor {
+
+       /** @var LoggerInterface instance for all JobExecutor instances */
+       private static $logger;
+
+       /**
+        * @param $jobEvent array the job event
+        * @return array containing the response status and the message
+        */
+       public function execute( $jobEvent ) {
+               $jobCreateResult = $this->getJobFromParams( $jobEvent );
+
+               if ( !$jobCreateResult['status'] ) {
+                       $this->logger()->error( $jobCreateResult['message'] );
+                       return $jobCreateResult;
+               }
+
+               $job = $jobCreateResult['job'];
+               $lbFactory = 
MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
+
+               WebRequest::overrideRequestId( $job->getRequestId() );
+
+               // Actually execute the job
+               try {
+                       $fnameTrxOwner = get_class( $job ) . '::run';
+
+                       $lbFactory->beginMasterChanges( $fnameTrxOwner );
+                       $status = $job->run();
+                       $message = $job->getLastError();
+                       $lbFactory->commitMasterChanges( $fnameTrxOwner );
+
+                       if ( !$status ) {
+                               $this->logger()->error( $job->toString() . " 
error={$message}" );
+                       }
+
+                       // Important: this must be the last deferred update 
added (T100085, T154425)
+                       DeferredUpdates::addCallableUpdate( [ 
JobQueueGroup::class, 'pushLazyJobs' ] );
+                       // Run any deferred update tasks; doUpdates() manages 
transactions itself
+                       DeferredUpdates::doUpdates();
+               } catch ( Exception $e ) {
+                       MWExceptionHandler::rollbackMasterChangesAndLog( $e );
+                       $status = false;
+                       $message = 'Error executing job: '
+                                          . $job->toString() . ' : '
+                                          . get_class( $e ) . ': ' . 
$e->getMessage();
+                       $this->logger()->error( $message );
+               }
+
+               // Always attempt to call teardown() even if Job throws 
exception.
+               try {
+                       $job->teardown( $status );
+               } catch ( Exception $e ) {
+                       $message = 'Error tearing down job: '
+                                          . $job->toString() . ' : '
+                                          . get_class( $e ) . ': ' . 
$e->getMessage();
+                       $this->logger()->error( $message );
+               }
+
+               // The JobRunner at this point makes some cleanups to prepare 
for
+               // the next Job execution. However since we run one job at a 
time
+               // we don't need that.
+
+               return [
+                       'status'  => $status,
+                       'message' => $message
+               ];
+       }
+
+       /**
+        * @param $jobEvent array containing the job EventBus event.
+        * @return array containing the Job, status and potentially error 
message
+        */
+       private function getJobFromParams( $jobEvent ) {
+               if ( !isset( $jobEvent['type'] ) ) {
+                       return [
+                               'status'  => false,
+                               'message' => 'Job event type is not defined'
+                       ];
+               }
+
+               $jobType = $jobEvent['type'];
+
+               if ( !isset( $jobEvent['page_title'] ) ) {
+                       return [
+                               'status'  => false,
+                               'message' => 'Job event page_title is not 
defined'
+                       ];
+               }
+
+               $title = Title::newFromDBkey( $jobEvent['page_title'] );
+
+               if ( is_null( $title ) ) {
+                       return [
+                               'status'  => false,
+                               'message' => 'Page ' . $jobEvent['page_title'] 
. ' does not exist'
+                       ];
+               }
+
+               $job = Job::factory( $jobType, $title, $jobEvent['params'] );
+
+               if ( is_null( $job ) ) {
+                       return [
+                               'status'  => false,
+                               'message' => 'Could not create a job from event'
+                       ];
+               }
+
+               return [
+                       'status' => true,
+                       'job'    => $job
+               ];
+       }
+
+       /**
+        * Returns a singleton logger instance for all JobExecutor instances.
+        * Use like: self::logger()->info( $mesage )
+        * We use this so we don't have to check if the logger has been created
+        * before attempting to log a message.
+        */
+       private static function logger() {
+               if ( !self::$logger ) {
+                       self::$logger = LoggerFactory::getInstance( 
'JobExecutor' );
+               }
+               return self::$logger;
+       }
+}
diff --git a/extension.json b/extension.json
index 238320b..f887d04 100644
--- a/extension.json
+++ b/extension.json
@@ -21,7 +21,8 @@
                "PurgeEventRelayerBus": "PurgeEventRelayerBus.php",
                "EventBusRCFeedEngine": "EventBusRCFeedEngine.php",
                "EventBusRCFeedFormatter": "EventBusRCFeedFormatter.php",
-               "JobQueueEventBus": "JobQueueEventBus.php"
+               "JobQueueEventBus": "JobQueueEventBus.php",
+               "JobExecutor": "JobExecutor.php"
        },
        "MessagesDirs": {
                "EventBus": [

-- 
To view, visit https://gerrit.wikimedia.org/r/369999
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: Ib1aaa58a730b20ee266a530150d684ae9782e6d2
Gerrit-PatchSet: 3
Gerrit-Project: mediawiki/extensions/EventBus
Gerrit-Branch: master
Gerrit-Owner: Ppchelko <ppche...@wikimedia.org>
Gerrit-Reviewer: Aaron Schulz <asch...@wikimedia.org>
Gerrit-Reviewer: GWicke <gwi...@wikimedia.org>
Gerrit-Reviewer: Giuseppe Lavagetto <glavage...@wikimedia.org>
Gerrit-Reviewer: Legoktm <lego...@member.fsf.org>
Gerrit-Reviewer: Mobrovac <mobro...@wikimedia.org>
Gerrit-Reviewer: Ppchelko <ppche...@wikimedia.org>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to