Sbisson has uploaded a new change for review. ( 
https://gerrit.wikimedia.org/r/405743 )

Change subject: Improve error-handling for OptInController
......................................................................

Improve error-handling for OptInController

* Better logging for failures (before it just logged
  the exception, now we also say what happened)
* Rollback all databases on failure.
* Use MWCallableUpdate.  Not sure if this is required,
  but it will make sure the callback is not run if the
  database in question rolls back before the callback starts.
* Also, use dependency injection.

Bug: T138310
Change-Id: I074586aa1a718bfb6905e33ce999ad8832fb6aaa
(cherry picked from commit 1aa4bb58969e5d26c4a690297879e9324562fe16)
---
M Hooks.php
M container.php
M extension.json
M includes/Import/OptInController.php
D includes/Import/OptInUpdate.php
5 files changed, 111 insertions(+), 70 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Flow 
refs/changes/43/405743/1

diff --git a/Hooks.php b/Hooks.php
index de887c1..052fe03 100644
--- a/Hooks.php
+++ b/Hooks.php
@@ -8,7 +8,7 @@
 use Flow\Exception\PermissionException;
 use Flow\Data\Listener\RecentChangesListener;
 use Flow\Formatter\CheckUserQuery;
-use Flow\Import\OptInUpdate;
+use Flow\Import\OptInController;
 use Flow\Model\UUID;
 use Flow\OccupationController;
 use Flow\SpamFilter\AbuseFilter;
@@ -1754,20 +1754,20 @@
                $after = $user->getBoolOption( BETA_FEATURE_FLOW_USER_TALK_PAGE 
);
                $action = null;
 
+               $optInController = Flow\Container::get( 'controller.opt_in' );
                if ( !$before && $after ) {
-                       $action = OptInUpdate::$ENABLE;
+                       $action = OptInController::$ENABLE;
                        // Check if the user had a flow board
-                       $c = new Flow\Import\OptInController();
-                       if ( !$c->hasFlowBoardArchive( $user ) ) {
+                       if ( !$optInController->hasFlowBoardArchive( $user ) ) {
                                // Enable the guided tour by setting the cookie
                                
RequestContext::getMain()->getRequest()->response()->setCookie( 
'Flow_optIn_guidedTour', '1' );
                        }
                } elseif ( $before && !$after ) {
-                       $action = OptInUpdate::$DISABLE;
+                       $action = OptInController::$DISABLE;
                }
 
                if ( $action ) {
-                       DeferredUpdates::addUpdate( new OptInUpdate( $action, 
$user->getTalkPage(), $user ) );
+                       $optInController->initiateChange( $action, 
$user->getTalkPage(), $user );
                }
 
                return true;
diff --git a/container.php b/container.php
index e7ab7df..ff79ba9 100644
--- a/container.php
+++ b/container.php
@@ -781,6 +781,22 @@
 // must always happen before calling flow code.
 $c['occupation_controller'] = FlowHooks::getOccupationController();
 
+$c['helper.archive_name'] = function ( $c ) {
+       return new Flow\Import\ArchiveNameHelper();
+};
+
+$c['controller.opt_in'] = function ( $c ) {
+       return new Flow\Import\OptInController(
+               $c['occupation_controller'],
+               $c['controller.notification'],
+               $c['helper.archive_name'],
+               $c['db.factory'],
+               $c['default_logger'],
+               $c['occupation_controller']->getTalkpageManager()
+
+       );
+};
+
 $c['controller.notification'] = function ( $c ) {
        global $wgContLang;
        return new Flow\NotificationController( $wgContLang, 
$c['repository.tree'] );
diff --git a/extension.json b/extension.json
index ce0ab2d..e766273 100644
--- a/extension.json
+++ b/extension.json
@@ -1109,7 +1109,6 @@
                "Flow\\Import\\LiquidThreadsApi\\ScriptedImportRevision": 
"includes/Import/LiquidThreadsApi/Objects.php",
                "Flow\\Import\\LiquidThreadsApi\\TopicIterator": 
"includes/Import/LiquidThreadsApi/Iterators.php",
                "Flow\\Import\\OptInController": 
"includes/Import/OptInController.php",
-               "Flow\\Import\\OptInUpdate": "includes/Import/OptInUpdate.php",
                "Flow\\Import\\PageImportState": "includes/Import/Importer.php",
                "Flow\\Import\\Plain\\ImportHeader": 
"includes/Import/Plain/ImportHeader.php",
                "Flow\\Import\\Plain\\ObjectRevision": 
"includes/Import/Plain/ObjectRevision.php",
diff --git a/includes/Import/OptInController.php 
b/includes/Import/OptInController.php
index 7fd1171..49d9e84 100644
--- a/includes/Import/OptInController.php
+++ b/includes/Import/OptInController.php
@@ -4,7 +4,10 @@
 
 use DateTime;
 use DateTimeZone;
+use DeferredUpdates;
 use DerivativeContext;
+use Exception;
+use Flow\DbFactory;
 use Flow\Collection\HeaderCollection;
 use Flow\Content\BoardContent;
 use Flow\Exception\InvalidDataException;
@@ -14,7 +17,9 @@
 use Flow\WorkflowLoader;
 use Flow\WorkflowLoaderFactory;
 use IContextSource;
+use Psr\Log\LoggerInterface;
 use MovePage;
+use MWExceptionHandler;
 use Parser;
 use ParserOptions;
 use RequestContext;
@@ -29,6 +34,8 @@
  * Entry point for enabling Flow on a page.
  */
 class OptInController {
+       public static $ENABLE = 'enable';
+       public static $DISABLE = 'disable';
 
        /**
         * @var OccupationController
@@ -46,6 +53,16 @@
        private $archiveNameHelper;
 
        /**
+        * @var DbFactory
+        */
+       private $dbFactory;
+
+       /**
+        * @var LoggerInterface
+        */
+       private $logger;
+
+       /**
         * @var IContextSource
         */
        private $context;
@@ -55,16 +72,83 @@
         */
        private $user;
 
-       public function __construct() {
-               $this->occupationController = Container::get( 
'occupation_controller' );
-               $this->notificationController = Container::get( 
'controller.notification' );
-               $this->archiveNameHelper = new ArchiveNameHelper();
-               $this->user = $this->occupationController->getTalkpageManager();
+       /**
+        * @param OccupationController $occupationController
+        * @param NotificationController $notificationController
+        * @param ArchiveNameHelper $archiveNameHelper
+        * @param DbFactory $dbFactory
+        * @param LoggerInterface $logger Logger for errors and exceptions
+        * @param User $scriptUser User that takes actions, such as creating 
the board or
+        *   editing descriptions
+        */
+       public function __construct(
+               OccupationController $occupationController,
+               NotificationController $notificationController,
+               ArchiveNameHelper $archiveNameHelper,
+               DbFactory $dbFactory,
+               LoggerInterface $logger,
+               User $scriptUser
+       ) {
+               $this->occupationController = $occupationController;
+               $this->notificationController = $notificationController;
+               $this->archiveNameHelper = $archiveNameHelper;
+               $this->dbFactory = $dbFactory;
+               $this->logger = $logger;
+               $this->user = $scriptUser;
                $this->context = new DerivativeContext( 
RequestContext::getMain() );
                $this->context->setUser( $this->user );
        }
 
        /**
+        * @param string $action Action to take, self::ENABLE or self::DISABLE
+        * @param Title $talkpage Title of user's talk page
+        * @param User $user User that owns the talk page
+        */
+       public function initiateChange( $action, Title $talkpage, User $user ) {
+               $flowDbw = $this->dbFactory->getDB( DB_MASTER );
+               $wikiDbw = $this->dbFactory->getWikiDB( DB_MASTER );
+
+               $outerMethod = __METHOD__;
+               $logger = $this->logger;
+
+               // We need both since we use both databases.
+               DeferredUpdates::addCallableUpdate(
+                       function () use ( $logger, $outerMethod, $wikiDbw, 
$action, $talkpage, $user ) {
+                               DeferredUpdates::addCallableUpdate(
+                                       function () use ( $logger, 
$outerMethod, $action, $talkpage, $user ) {
+                                               try {
+                                                       if ( $action === 
self::$ENABLE ) {
+                                                               $this->enable( 
$talkpage, $user );
+                                                       } elseif ( $action === 
self::$DISABLE ) {
+                                                               $this->disable( 
$talkpage );
+                                                       } else {
+                                                               $logger->error( 
$outerMethod . ': unrecognized action: ' . $action );
+                                                       }
+                                               } catch ( Exception $e ) {
+                                                       $logger->error(
+                                                               $outerMethod . 
' failed to {action} Flow on \'{talkpage}\' for user \'{user}\'.  Exception: 
{exception}',
+                                                               [
+                                                                       
'action' => $action,
+                                                                       
'talkpage' => $talkpage,
+                                                                       'user' 
=> $user,
+                                                                       
'exception' => $e,
+                                                               ]
+                                                       );
+                                                       // rollback both Flow 
and Core DBs
+                                                       
MWExceptionHandler::rollbackMasterChangesAndLog( $e );
+                                                       
$this->dbFactory->getDB( DB_MASTER )->rollback( $outerMethod );
+                                               }
+                                       },
+                                       $outerMethod,
+                                       $wikiDbw
+                               );
+                       },
+                       __METHOD__,
+                       $flowDbw
+               );
+       }
+
+       /**
         * @param Title $title
         * @param User $user
         */
diff --git a/includes/Import/OptInUpdate.php b/includes/Import/OptInUpdate.php
deleted file mode 100644
index 3c1a0f7..0000000
--- a/includes/Import/OptInUpdate.php
+++ /dev/null
@@ -1,58 +0,0 @@
-<?php
-
-namespace Flow\Import;
-
-use DeferrableUpdate;
-use MWExceptionHandler;
-use Title;
-use User;
-
-class OptInUpdate implements DeferrableUpdate {
-
-       public static $ENABLE = 'enable';
-       public static $DISABLE = 'disable';
-
-       /**
-        * @var string
-        */
-       protected $action;
-
-       /**
-        * @var Title
-        */
-       protected $talkpage;
-
-       /**
-        * @var User
-        */
-       protected $user;
-
-       /**
-        * @param string $action
-        * @param Title $talkpage
-        * @param User $user
-        */
-       public function __construct( $action, Title $talkpage, User $user ) {
-               $this->action = $action;
-               $this->talkpage = $talkpage;
-               $this->user = $user;
-       }
-
-       /**
-        * Enable or disable Flow on a talk page
-        */
-       function doUpdate() {
-               $c = new OptInController();
-               try {
-                       if ( $this->action === self::$ENABLE ) {
-                               $c->enable( $this->talkpage, $this->user );
-                       } elseif ( $this->action === self::$DISABLE ) {
-                               $c->disable( $this->talkpage );
-                       } else {
-                               wfLogWarning( 'OptInUpdate: unrecognized 
action: ' . $this->action );
-                       }
-               } catch ( \Exception $e ) {
-                       MWExceptionHandler::logException( $e );
-               }
-       }
-}

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: I074586aa1a718bfb6905e33ce999ad8832fb6aaa
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Flow
Gerrit-Branch: wmf/1.31.0-wmf.17
Gerrit-Owner: Sbisson <sbis...@wikimedia.org>
Gerrit-Reviewer: Mattflaschen <mflasc...@wikimedia.org>

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

Reply via email to