Gergő Tisza has uploaded a new change for review.
https://gerrit.wikimedia.org/r/297537
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
---
M includes/GlobalRename/GlobalRenameUser.php
M includes/GlobalRename/GlobalRenameUserStatus.php
M includes/LocalRenameJob/LocalRenameJob.php
3 files changed, 71 insertions(+), 7 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/CentralAuth
refs/changes/37/297537/1
diff --git a/includes/GlobalRename/GlobalRenameUser.php
b/includes/GlobalRename/GlobalRenameUser.php
index 59b69b8..6aa831a 100644
--- a/includes/GlobalRename/GlobalRenameUser.php
+++ b/includes/GlobalRename/GlobalRenameUser.php
@@ -173,9 +173,11 @@
*/
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 );
+ foreach ( $this->renameuserStatus->getStatuses( 'master' ) 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..5d26027 100644
--- a/includes/GlobalRename/GlobalRenameUserStatus.php
+++ b/includes/GlobalRename/GlobalRenameUserStatus.php
@@ -96,15 +96,17 @@
* Get a user's rename status for all wikis.
* Returns an array ( wiki => status )
*
+ * @param string|null $useMaster Set to 'master' to query the master db
+ *
* @return array
*/
- public function getStatuses() {
- $dbr = $this->getDB();
+ public function getStatuses( $useMaster = null ) {
+ $db = $this->getDB( $useMaster === 'master' ? DB_MASTER :
DB_SLAVE );
- $res = $dbr->select(
+ $res = $db->select(
'renameuser_status',
array( 'ru_wiki', 'ru_status' ),
- array( $this->getNameWhereClause( $dbr ) ),
+ array( $this->getNameWhereClause( $db ) ),
__METHOD__
);
@@ -117,6 +119,37 @@
}
/**
+ * Get the next wiki on which the rename should be performed.
+ *
+ * @param string|null $useMaster Set to 'master' to query the master db
+ *
+ * @return string|null
+ */
+ public function getNextWiki( $useMaster = null ) {
+ $nextWiki = null;
+ foreach ( $this->getStatuses( $useMaster ) as $wiki => $status
) {
+ if ( $status === 'queued' ) {
+ $nextWiki = $wiki;
+ break;
+ }
+ }
+ return $nextWiki;
+ }
+
+ /**
+ * Get a user's rename status for the current wiki.
+ *
+ * @param string|null $useMaster Set to 'master' to query the master db
+ *
+ * @return string|null Null means no rename pending for this user on
the current wiki (possibly
+ * because it has finished already).
+ */
+ public function getStatus( $useMaster = null ) {
+ $statuses = $this->getStatuses( $useMaster );
+ 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..367ab72 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( 'master' );
+ 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,18 @@
protected function updateStatus( $status ) {
$this->renameuserStatus->setStatus( wfWikiID(), $status );
}
+
+ protected function scheduleNextWiki() {
+ $job = new static( $this->getTitle(), $this->getParams() );
+ $nextWiki = null;
+ foreach ( $this->renameuserStatus->getStatuses( 'master' ) 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/297537
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: master
Gerrit-Owner: Gergő Tisza <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits