Add maintenance script to recompute notification counts

Generally applicable, but intended for users affected by the
login-success phantom notifications bug.

Bug: T220762
Change-Id: Ica428bfc19e0555564ca04d80ac5009197401aaf
This commit is contained in:
Roan Kattouw 2019-04-12 17:48:01 -07:00
parent 61a839315a
commit 754ec9ef11
2 changed files with 88 additions and 0 deletions

View file

@ -1009,6 +1009,7 @@
"NotificationPager": "includes/special/NotificationPager.php",
"NotificationsTest": "tests/phpunit/NotificationsTest.php",
"ProcessEchoEmailBatch": "maintenance/processEchoEmailBatch.php",
"RecomputeNotifCounts": "maintenance/recomputeNotifCounts.php",
"RemoveInvalidNotification": "maintenance/removeInvalidNotification.php",
"RemoveOrphanedEvents": "maintenance/removeOrphanedEvents.php",
"ResourceLoaderEchoImageModule": "includes/ResourceLoaderEchoImageModule.php",

View file

@ -0,0 +1,87 @@
<?php
/**
* Recompute notification counts for all users.
*
* @ingroup Maintenance
*/
require_once getenv( 'MW_INSTALL_PATH' ) !== false
? getenv( 'MW_INSTALL_PATH' ) . '/maintenance/Maintenance.php'
: __DIR__ . '/../../../maintenance/Maintenance.php';
/**
* Maintenance script that recomputes notification counts
*
* @ingroup Maintenance
*/
class RecomputeNotifCounts extends Maintenance {
public function __construct() {
parent::__construct();
$this->addDescription( 'Recompute notification counts for all users.' );
$this->addOption( 'user-ids', 'Comma-separated list of users to recompute notification counts for', false, true );
$this->addOption( 'notif-types', 'Recompute counts for all users who have unread notifications of one of these types (comma-separated)',
false, true );
$this->setBatchSize( 500 );
$this->requireExtension( 'Echo' );
}
public function execute() {
$dbFactory = MWEchoDbFactory::newFromDefault();
$dbwEcho = $dbFactory->getEchoDb( DB_MASTER );
$dbrEcho = $dbFactory->getEchoDb( DB_REPLICA );
$dbr = wfGetDB( DB_REPLICA );
$userIDs = $this->getOption( 'user-ids' );
$userIDs = $userIDs ? explode( ',', $userIDs ) : null;
$notifTypes = $this->getOption( 'notif-types' );
$notifTypes = $notifTypes ? explode( ',', $notifTypes ) : null;
if ( $userIDs ) {
$userIterator = array_chunk( $userIDs, $this->getBatchSize() );
} elseif ( $notifTypes ) {
$userIterator = new BatchRowIterator(
$dbrEcho,
[ 'echo_event', 'echo_notification' ],
'notification_user',
$this->getBatchSize()
);
$userIterator->addJoinConditions( [
'echo_notification' => [ 'INNER JOIN', 'notification_event=event_id' ]
] );
$userIterator->addConditions( [
'event_type' => $notifTypes,
'notification_read_timestamp' => null
] );
$userIterator->addOptions( [
'GROUP BY' => 'notification_user'
] );
} else {
$userQuery = User::getQueryInfo();
$userIterator = new BatchRowIterator( $dbr, $userQuery['tables'], 'user_id', $this->getBatchSize() );
$userIterator->setFetchColumns( $userQuery['fields'] );
$userIterator->addJoinConditions( $userQuery['joins'] );
}
$count = 0;
foreach ( $userIterator as $batch ) {
foreach ( $batch as $rowOrID ) {
if ( is_object( $rowOrID ) && isset( $rowOrID->user_id ) ) {
$user = User::newFromRow( $rowOrID );
} else {
$user = User::newFromId( is_object( $rowOrID ) ? $rowOrID->notification_user : $rowOrID );
}
$notifUser = MWEchoNotifUser::newFromUser( $user );
$notifUser->resetNotificationCount();
}
$count += count( $batch );
$this->output( "$count users' counts recomputed.\n" );
$dbFactory->waitForSlaves();
}
}
}
$maintClass = RecomputeNotifCounts::class;
require_once RUN_MAINTENANCE_IF_MAIN;