X-Git-Url: https://git.heureux-cyclage.org/?p=lhc%2Fweb%2Fwiklou.git;a=blobdiff_plain;f=includes%2Fuser%2FUserGroupMembership.php;h=89cdc5f1946990fef888f0dee5468953b7008513;hp=f771f4285e76f132e8acb138d9f2b6cd4c879d6e;hb=f22a83c3b0f2a8d568cdade08404ea9469661f1b;hpb=74426f3cf796b149f1ae445e41815bbe148640b2 diff --git a/includes/user/UserGroupMembership.php b/includes/user/UserGroupMembership.php index f771f4285e..89cdc5f194 100644 --- a/includes/user/UserGroupMembership.php +++ b/includes/user/UserGroupMembership.php @@ -21,6 +21,7 @@ */ use Wikimedia\Rdbms\IDatabase; +use MediaWiki\MediaWikiServices; /** * Represents a "user group membership" -- a specific instance of a user belonging @@ -158,7 +159,7 @@ class UserGroupMembership { } // Purge old, expired memberships from the DB - self::purgeExpired( $dbw ); + JobQueueGroup::singleton()->push( new UserGroupExpiryJob() ); // Check that the values make sense if ( $this->group === null ) { @@ -229,45 +230,72 @@ class UserGroupMembership { public function isExpired() { if ( !$this->expiry ) { return false; - } else { - return wfTimestampNow() > $this->expiry; } + return wfTimestampNow() > $this->expiry; } /** * Purge expired memberships from the user_groups table * - * @param IDatabase|null $dbw + * @return int|bool false if purging wasn't attempted (e.g. because of + * readonly), the number of rows purged (might be 0) otherwise */ - public static function purgeExpired( IDatabase $dbw = null ) { - if ( wfReadOnly() ) { - return; + public static function purgeExpired() { + $services = MediaWikiServices::getInstance(); + if ( $services->getReadOnlyMode()->isReadOnly() ) { + return false; } - if ( $dbw === null ) { - $dbw = wfGetDB( DB_MASTER ); - } + $lbFactory = $services->getDBLoadBalancerFactory(); + $ticket = $lbFactory->getEmptyTransactionTicket( __METHOD__ ); + $dbw = $services->getDBLoadBalancer()->getConnection( DB_MASTER ); - DeferredUpdates::addUpdate( new AtomicSectionUpdate( - $dbw, - __METHOD__, - function ( IDatabase $dbw, $fname ) { - $expiryCond = [ 'ug_expiry < ' . $dbw->addQuotes( $dbw->timestamp() ) ]; - $res = $dbw->select( 'user_groups', self::selectFields(), $expiryCond, $fname ); + $lockKey = $dbw->getDomainID() . ':usergroups-prune'; // specific to this wiki + $scopedLock = $dbw->getScopedLockAndFlush( $lockKey, __METHOD__, 0 ); + if ( !$scopedLock ) { + return false; // already running + } - // save an array of users/groups to insert to user_former_groups - $usersAndGroups = []; + $now = time(); + $purgedRows = 0; + do { + $dbw->startAtomic( __METHOD__ ); + + $res = $dbw->select( + 'user_groups', + self::selectFields(), + [ 'ug_expiry < ' . $dbw->addQuotes( $dbw->timestamp( $now ) ) ], + __METHOD__, + [ 'FOR UPDATE', 'LIMIT' => 100 ] + ); + + if ( $res->numRows() > 0 ) { + $insertData = []; // array of users/groups to insert to user_former_groups + $deleteCond = []; // array for deleting the rows that are to be moved around foreach ( $res as $row ) { - $usersAndGroups[] = [ 'ufg_user' => $row->ug_user, 'ufg_group' => $row->ug_group ]; + $insertData[] = [ 'ufg_user' => $row->ug_user, 'ufg_group' => $row->ug_group ]; + $deleteCond[] = $dbw->makeList( + [ 'ug_user' => $row->ug_user, 'ug_group' => $row->ug_group ], + $dbw::LIST_AND + ); } + // Delete the rows we're about to move + $dbw->delete( + 'user_groups', + $dbw->makeList( $deleteCond, $dbw::LIST_OR ), + __METHOD__ + ); + // Push the groups to user_former_groups + $dbw->insert( 'user_former_groups', $insertData, __METHOD__, [ 'IGNORE' ] ); + // Count how many rows were purged + $purgedRows += $res->numRows(); + } - // delete 'em all - $dbw->delete( 'user_groups', $expiryCond, $fname ); + $dbw->endAtomic( __METHOD__ ); - // and push the groups to user_former_groups - $dbw->insert( 'user_former_groups', $usersAndGroups, __METHOD__, [ 'IGNORE' ] ); - } - ) ); + $lbFactory->commitAndWaitForReplication( __METHOD__, $ticket ); + } while ( $res->numRows() > 0 ); + return $purgedRows; } /** @@ -325,9 +353,8 @@ class UserGroupMembership { $ugm = self::newFromRow( $row ); if ( !$ugm->isExpired() ) { return $ugm; - } else { - return false; } + return false; } /** @@ -390,9 +417,8 @@ class UserGroupMembership { } return $context->msg( 'group-membership-link-with-expiry' ) ->params( $groupLink, $expiryDT, $expiryD, $expiryT )->text(); - } else { - return $groupLink; } + return $groupLink; } /**