jenkins-bot has submitted this change and it was merged.
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, 59 insertions(+), 9 deletions(-)
Approvals:
Anomie: Looks good to me, approved
jenkins-bot: Verified
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 < [email protected] >
*/
-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/297537
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I00f2710080897030a3e44a8c8490d991d703bb21
Gerrit-PatchSet: 3
Gerrit-Project: mediawiki/extensions/CentralAuth
Gerrit-Branch: master
Gerrit-Owner: Gergő Tisza <[email protected]>
Gerrit-Reviewer: Anomie <[email protected]>
Gerrit-Reviewer: Gergő Tisza <[email protected]>
Gerrit-Reviewer: Krinkle <[email protected]>
Gerrit-Reviewer: Legoktm <[email protected]>
Gerrit-Reviewer: Ori.livneh <[email protected]>
Gerrit-Reviewer: jenkins-bot <>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits