From 2549c49562272d25a4cca07c11ad6ba6a3cf1968 Mon Sep 17 00:00:00 2001 From: Timo Tijhof Date: Wed, 19 Sep 2012 02:24:35 +0200 Subject: [PATCH] (bug 40340) Fix cache issues with changing user groups * migrateUserGroup.php: Call User::invalidateCache * While at it, also fix the issue where User::clearInstanceCache did not clear cache for User::getGroups. Although it does clear the caches of methods used to calculate other group-related lists (such as User::getEffectiveGroups), the one for the query from user_groups was still cached in $this->mGroups. Presumably this was forgotten when this pattern was introduced as the instance cache precedes the user_group table. Change-Id: I22abdba00f8ccf587a3d7696e57970ed4653afc8 --- includes/User.php | 1 + maintenance/migrateUserGroup.php | 31 ++++++++++++++++++++++++++++--- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/includes/User.php b/includes/User.php index 91e75b530e..a6958c805f 100644 --- a/includes/User.php +++ b/includes/User.php @@ -1201,6 +1201,7 @@ class User { $this->mRights = null; $this->mEffectiveGroups = null; $this->mImplicitGroups = null; + $this->mGroups = null; $this->mOptions = null; $this->mOptionsLoaded = false; $this->mEditCount = null; diff --git a/maintenance/migrateUserGroup.php b/maintenance/migrateUserGroup.php index 496af7237b..f3e5957c60 100644 --- a/maintenance/migrateUserGroup.php +++ b/maintenance/migrateUserGroup.php @@ -55,7 +55,9 @@ class MigrateUserGroup extends Maintenance { $blockEnd = $start + $this->mBatchSize - 1; // Migrate users over in batches... while ( $blockEnd <= $end ) { + $affected = 0; $this->output( "Doing users $blockStart to $blockEnd\n" ); + $dbw->begin( __METHOD__ ); $dbw->update( 'user_groups', array( 'ug_group' => $newGroup ), @@ -64,19 +66,42 @@ class MigrateUserGroup extends Maintenance { __METHOD__, array( 'IGNORE' ) ); - $count += $dbw->affectedRows(); + $affected += $dbw->affectedRows(); + // Delete rows that the UPDATE operation above had to ignore. + // This happens when a user is in both the old and new group. + // Updating the row for the old group membership failed since + // user/group is UNIQUE. $dbw->delete( 'user_groups', array( 'ug_group' => $oldGroup, "ug_user BETWEEN $blockStart AND $blockEnd" ), __METHOD__ ); - $count += $dbw->affectedRows(); + $affected += $dbw->affectedRows(); $dbw->commit( __METHOD__ ); + + // Clear cache for the affected users (bug 40340) + if ( $affected > 0 ) { + // XXX: This also invalidates cache of unaffected users that + // were in the new group and not in the group. + $res = $dbw->select( 'user_groups', 'ug_user', + array( 'ug_group' => $newGroup, + "ug_user BETWEEN $blockStart AND $blockEnd" ), + __METHOD__ + ); + if ( $res !== false ) { + foreach ( $res as $row ) { + $user = User::newFromId( $row->ug_user ); + $user->invalidateCache(); + } + } + } + + $count += $affected; $blockStart += $this->mBatchSize; $blockEnd += $this->mBatchSize; wfWaitForSlaves(); } - $this->output( "Done! $count user(s) in group '$oldGroup' are now in '$newGroup' instead.\n" ); + $this->output( "Done! $count users in group '$oldGroup' are now in '$newGroup' instead.\n" ); } } -- 2.20.1