Legoktm has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/297697

Change subject: Make LocalRename jobs run sequentially
......................................................................

Make LocalRename jobs run sequentially

Running the job parallel on each wiki caused problems for users with
many accounts due to DB errors when all jobs tried to change the
central user record at the same time. Run one wiki after the other instead,
with each job scheduling the next job when it is finished.

Bug: T137973
Change-Id: I00f2710080897030a3e44a8c8490d991d703bb21
(cherry picked from commit 053b4ce1e137d7bbade69bcf2f8c6dcd17e0651f)
---
M includes/GlobalRename/GlobalRenameUser.php
M includes/GlobalRename/GlobalRenameUserStatus.php
M includes/LocalRenameJob/LocalRenameJob.php
3 files changed, 59 insertions(+), 9 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/CentralAuth 
refs/changes/97/297697/1

diff --git a/includes/GlobalRename/GlobalRenameUser.php 
b/includes/GlobalRename/GlobalRenameUser.php
index 59b69b8..f3a6c8d 100644
--- a/includes/GlobalRename/GlobalRenameUser.php
+++ b/includes/GlobalRename/GlobalRenameUser.php
@@ -173,9 +173,12 @@
         */
        private function injectLocalRenameUserJobs( array $wikis, array 
$options ) {
                $job = $this->getJob( $options );
-               // Submit the jobs.
-               foreach( $wikis as $wiki ) {
-                       call_user_func( $this->jobQueueGroupGenerator, $wiki 
)->push( $job );
+               $statuses = $this->renameuserStatus->getStatuses( 
GlobalRenameUserStatus::READ_LATEST );
+               foreach ( $statuses as $wiki => $status ) {
+                       if ( $status === 'queued' ) {
+                               call_user_func( $this->jobQueueGroupGenerator, 
$wiki )->push( $job );
+                               break;
+                       }
                }
        }
 
diff --git a/includes/GlobalRename/GlobalRenameUserStatus.php 
b/includes/GlobalRename/GlobalRenameUserStatus.php
index 1d2bb6e..ecb6101 100644
--- a/includes/GlobalRename/GlobalRenameUserStatus.php
+++ b/includes/GlobalRename/GlobalRenameUserStatus.php
@@ -9,7 +9,7 @@
  * @author Marius Hoch < h...@online.de >
  */
 
-class GlobalRenameUserStatus {
+class GlobalRenameUserStatus implements IDBAccessObject {
 
        /**
         * Either old or new name of the user
@@ -96,16 +96,20 @@
         * Get a user's rename status for all wikis.
         * Returns an array ( wiki => status )
         *
+        * @param integer $flags IDBAccessObject flags
+        *
         * @return array
         */
-       public function getStatuses() {
-               $dbr = $this->getDB();
+       public function getStatuses( $flags = 0 ) {
+               list( $index, $options ) = DBAccessObjectUtils::getDBOptions( 
$flags );
+               $db = $this->getDB( $index );
 
-               $res = $dbr->select(
+               $res = $db->select(
                        'renameuser_status',
                        array( 'ru_wiki', 'ru_status' ),
-                       array( $this->getNameWhereClause( $dbr ) ),
-                       __METHOD__
+                       array( $this->getNameWhereClause( $db ) ),
+                       __METHOD__,
+                       $options
                );
 
                $statuses = array();
@@ -117,6 +121,19 @@
        }
 
        /**
+        * Get a user's rename status for the current wiki.
+        *
+        * @param integer $flags IDBAccessObject flags
+        *
+        * @return string|null Null means no rename pending for this user on 
the current wiki (possibly
+        *   because it has finished already).
+        */
+       public function getStatus( $flags = 0 ) {
+               $statuses = $this->getStatuses( $flags );
+               return isset( $statuses[wfWikiID()] ) ? $statuses[wfWikiID()] : 
null;
+       }
+
+       /**
         * Set the rename status for a certain wiki
         *
         * @param string $wiki
diff --git a/includes/LocalRenameJob/LocalRenameJob.php 
b/includes/LocalRenameJob/LocalRenameJob.php
index c4285b6..d696338 100644
--- a/includes/LocalRenameJob/LocalRenameJob.php
+++ b/includes/LocalRenameJob/LocalRenameJob.php
@@ -1,5 +1,7 @@
 <?php
 
+use MediaWiki\Logger\LoggerFactory;
+
 /**
  * Base class for jobs that change a user's
  * name. Intended to be run on local wikis
@@ -13,6 +15,18 @@
 
        public function run() {
                $this->setRenameUserStatus( new GlobalRenameUserStatus( 
$this->params['to'] ) );
+
+               // bail if it's already done or in progress
+               $status = $this->renameuserStatus->getStatus( 
GlobalRenameUserStatus::READ_LATEST );
+               if ( $status !== 'queued' && $status !== 'failed' ) {
+                       LoggerFactory::getInstance( 'rename' )->info( 'skipping 
duplicate rename from {user}', [
+                               'user' => $this->params['from'],
+                               'to' => $this->params['to'],
+                               'status' => $status,
+                       ] );
+                       return true;
+               }
+
                if ( isset( $this->params['session'] ) ) {
                        // Don't carry over users or sessions because it's 
going to be wrong
                        // across wikis
@@ -25,6 +39,7 @@
                }
                try {
                        $this->doRun();
+                       $this->scheduleNextWiki();
                } catch ( Exception $e ) {
                        // This will lock the user out of their account
                        // until a sysadmin intervenes
@@ -87,4 +102,19 @@
        protected function updateStatus( $status ) {
                $this->renameuserStatus->setStatus( wfWikiID(), $status );
        }
+
+       protected function scheduleNextWiki() {
+               $job = new static( $this->getTitle(), $this->getParams() );
+               $nextWiki = null;
+               $statuses = $this->renameuserStatus->getStatuses( 
GlobalRenameUserStatus::READ_LATEST );
+               foreach ( $statuses as $wiki => $status ) {
+                       if ( $status === 'queued' && $wiki !== wfWikiID() ) {
+                               $nextWiki = $wiki;
+                               break;
+                       }
+               }
+               if ( $nextWiki ) {
+                       JobQueueGroup::singleton( $nextWiki )->push( $job );
+               }
+       }
 }

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: I00f2710080897030a3e44a8c8490d991d703bb21
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/CentralAuth
Gerrit-Branch: wmf/1.28.0-wmf.8
Gerrit-Owner: Legoktm <legoktm.wikipe...@gmail.com>

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

Reply via email to