diff options
Diffstat (limited to 'Echo/includes/mapper/NotificationMapper.php')
-rw-r--r-- | Echo/includes/mapper/NotificationMapper.php | 128 |
1 files changed, 44 insertions, 84 deletions
diff --git a/Echo/includes/mapper/NotificationMapper.php b/Echo/includes/mapper/NotificationMapper.php index 3e9dc2f6..4e572a78 100644 --- a/Echo/includes/mapper/NotificationMapper.php +++ b/Echo/includes/mapper/NotificationMapper.php @@ -23,31 +23,11 @@ class EchoNotificationMapper extends EchoAbstractMapper { $dbw, __METHOD__, function ( IDatabase $dbw, $fname ) use ( $row, $listeners ) { - // Reset the bundle base if this notification has a display hash - // the result of this operation is that all previous notifications - // with the same display hash are set to non-base because new record - // is becoming the bundle base - if ( $row['notification_bundle_display_hash'] ) { - $dbw->update( - 'echo_notification', - [ 'notification_bundle_base' => 0 ], - [ - 'notification_user' => $row['notification_user'], - 'notification_bundle_display_hash' => - $row['notification_bundle_display_hash'], - 'notification_bundle_base' => 1 - ], - $fname - ); - } - $row['notification_timestamp'] = $dbw->timestamp( $row['notification_timestamp'] ); - $res = $dbw->insert( 'echo_notification', $row, $fname ); - if ( $res ) { - foreach ( $listeners as $listener ) { - $dbw->onTransactionIdle( $listener ); - } + $dbw->insert( 'echo_notification', $row, $fname ); + foreach ( $listeners as $listener ) { + $dbw->onTransactionCommitOrIdle( $listener, $fname ); } } ) ); @@ -55,7 +35,7 @@ class EchoNotificationMapper extends EchoAbstractMapper { /** * Extract the offset used for notification list - * @param string $continue String Used for offset + * @param string|null $continue String Used for offset * @throws MWException * @return int[] */ @@ -84,11 +64,11 @@ class EchoNotificationMapper extends EchoAbstractMapper { * which is done via a deleteJob * @param User $user * @param int $limit - * @param string $continue Used for offset + * @param string|null $continue Used for offset * @param string[] $eventTypes * @param Title[]|null $titles If set, only return notifications for these pages. * To find notifications not associated with any page, add null as an element to this array. - * @param int $dbSource Use master or slave database + * @param int $dbSource Use master or replica database * @return EchoNotification[] */ public function fetchUnreadByUser( @@ -99,7 +79,7 @@ class EchoNotificationMapper extends EchoAbstractMapper { array $titles = null, $dbSource = DB_REPLICA ) { - $conds['notification_read_timestamp'] = null; + $conds = [ 'notification_read_timestamp' => null ]; if ( $titles ) { $conds['event_page_id'] = $this->getIdsForTitles( $titles ); if ( !$conds['event_page_id'] ) { @@ -117,11 +97,11 @@ class EchoNotificationMapper extends EchoAbstractMapper { * which is done via a deleteJob * @param User $user * @param int $limit - * @param string $continue Used for offset + * @param string|null $continue Used for offset * @param string[] $eventTypes * @param Title[]|null $titles If set, only return notifications for these pages. * To find notifications not associated with any page, add null as an element to this array. - * @param int $dbSource Use master or slave database + * @param int $dbSource Use master or replica database * @return EchoNotification[] */ public function fetchReadByUser( @@ -147,7 +127,7 @@ class EchoNotificationMapper extends EchoAbstractMapper { * * @param User $user the user to get notifications for * @param int $limit The maximum number of notifications to return - * @param string $continue Used for offset + * @param string|null $continue Used for offset * @param array $eventTypes Event types to load * @param array $excludeEventIds Event id's to exclude. * @param Title[]|null $titles If set, only return notifications for these pages. @@ -193,10 +173,10 @@ class EchoNotificationMapper extends EchoAbstractMapper { /** * @param User $user the user to get notifications for * @param int $limit The maximum number of notifications to return - * @param string $continue Used for offset + * @param string|null $continue Used for offset * @param array $eventTypes Event types to load * @param array $conds Additional query conditions. - * @param int $dbSource Use master or slave database + * @param int $dbSource Use master or replica database * @return EchoNotification[] */ protected function fetchByUserInternal( @@ -220,7 +200,7 @@ class EchoNotificationMapper extends EchoAbstractMapper { // the notification volume is in a reasonable amount for such case. The other option // is to denormalize notification table with event_type and lookup index. $conds = [ - 'notification_user' => $user->getID(), + 'notification_user' => $user->getId(), 'event_type' => $eventTypes, 'event_deleted' => 0, ] + $conds; @@ -237,7 +217,7 @@ class EchoNotificationMapper extends EchoAbstractMapper { $res = $dbr->select( [ 'echo_notification', 'echo_event' ], - '*', + EchoNotification::selectFields(), $conds, __METHOD__, [ @@ -263,7 +243,7 @@ class EchoNotificationMapper extends EchoAbstractMapper { $allNotifications[] = $notification; } } catch ( Exception $e ) { - $id = isset( $row->event_id ) ? $row->event_id : 'unknown event'; + $id = $row->event_id ?? 'unknown event'; wfDebugLog( 'Echo', __METHOD__ . ": Failed initializing event: $id" ); MWExceptionHandler::logException( $e ); } @@ -278,47 +258,18 @@ class EchoNotificationMapper extends EchoAbstractMapper { } /** - * Get the last notification in a set of bundle-able notifications by a bundle hash - * @param User $user - * @param string $bundleHash The hash used to identify a set of bundle-able notifications - * @return EchoNotification|false - */ - public function fetchNewestByUserBundleHash( User $user, $bundleHash ) { - $dbr = $this->dbFactory->getEchoDb( DB_REPLICA ); - - $row = $dbr->selectRow( - [ 'echo_notification', 'echo_event' ], - [ '*' ], - [ - 'notification_user' => $user->getId(), - 'notification_bundle_hash' => $bundleHash - ], - __METHOD__, - [ 'ORDER BY' => 'notification_timestamp DESC', 'LIMIT' => 1 ], - [ - 'echo_event' => [ 'LEFT JOIN', 'notification_event=event_id' ], - ] - ); - if ( $row ) { - return EchoNotification::newFromRow( $row ); - } else { - return false; - } - } - - /** * Fetch EchoNotifications by user and event IDs. * * @param User $user * @param int[] $eventIds * @return EchoNotification[]|false */ - public function fetchByUserEvents( User $user, $eventIds ) { + public function fetchByUserEvents( User $user, array $eventIds ) { $dbr = $this->dbFactory->getEchoDb( DB_REPLICA ); $result = $dbr->select( [ 'echo_notification', 'echo_event' ], - '*', + EchoNotification::selectFields(), [ 'notification_user' => $user->getId(), 'notification_event' => $eventIds @@ -352,7 +303,7 @@ class EchoNotificationMapper extends EchoAbstractMapper { $dbr = $this->dbFactory->getEchoDb( DB_REPLICA ); $row = $dbr->selectRow( [ 'echo_notification', 'echo_event' ], - [ '*' ], + EchoNotification::selectFields(), [ 'notification_user' => $user->getId(), 'event_deleted' => 0, @@ -383,38 +334,47 @@ class EchoNotificationMapper extends EchoAbstractMapper { */ public function deleteByUserEventOffset( User $user, $eventId ) { global $wgUpdateRowsPerQuery; + $eventMapper = new EchoEventMapper( $this->dbFactory ); $userId = $user->getId(); $dbw = $this->dbFactory->getEchoDb( DB_MASTER ); + $dbr = $this->dbFactory->getEchoDb( DB_REPLICA ); $lbFactory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory(); $ticket = $lbFactory->getEmptyTransactionTicket( __METHOD__ ); - $domainId = $dbw->getDomainId(); + $domainId = $dbw->getDomainID(); - $idsToDelete = $dbw->selectFieldValues( + $iterator = new BatchRowIterator( + $dbr, 'echo_notification', 'notification_event', - [ - 'notification_user' => $userId, - 'notification_event < ' . (int)$eventId - ], - __METHOD__ + $wgUpdateRowsPerQuery ); - if ( !$idsToDelete ) { - return true; - } - $success = true; - foreach ( array_chunk( $idsToDelete, $wgUpdateRowsPerQuery ) as $batch ) { - $success = $dbw->delete( + $iterator->addConditions( [ + 'notification_user' => $userId, + 'notification_event < ' . (int)$eventId + ] ); + + foreach ( $iterator as $batch ) { + $eventIds = []; + foreach ( $batch as $row ) { + $eventIds[] = $row->notification_event; + } + $dbw->delete( 'echo_notification', [ 'notification_user' => $userId, - 'notification_event' => $batch, + 'notification_event' => $eventIds, ], __METHOD__ - ) && $success; + ); + + // Find out which events are now orphaned, i.e. no longer referenced in echo_notifications + // (besides the rows we just deleted) or in echo_email_batch, and delete them + $eventMapper->deleteOrphanedEvents( $eventIds, $userId, 'echo_notification' ); + $lbFactory->commitAndWaitForReplication( __METHOD__, $ticket, [ 'domain' => $domainId ] ); } - return $success; + return true; } /** @@ -423,7 +383,7 @@ class EchoNotificationMapper extends EchoAbstractMapper { * @param int[] $eventIds * @return int[]|false */ - public function fetchUsersWithNotificationsForEvents( $eventIds ) { + public function fetchUsersWithNotificationsForEvents( array $eventIds ) { $dbr = $this->dbFactory->getEchoDb( DB_REPLICA ); $res = $dbr->select( |