From 51c766f82d42e8441bdd0341ffe39d8b3bdb5c02 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Thu, 4 Jun 2020 17:18:24 +0200 Subject: Temporarily cache the rooms in the notifier If we have multiple notifications to render for the same room we only do 1 query now. This e.g. heavily impacts the performance when creating "X started a call" push notifications. Signed-off-by: Joas Schilling --- lib/Notification/Notifier.php | 46 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 8 deletions(-) (limited to 'lib') diff --git a/lib/Notification/Notifier.php b/lib/Notification/Notifier.php index c336103e6..092cf186b 100644 --- a/lib/Notification/Notifier.php +++ b/lib/Notification/Notifier.php @@ -73,6 +73,9 @@ class Notifier implements INotifier { /** @var Definitions */ protected $definitions; + /** @var Room[] */ + protected $rooms = []; + public function __construct(IFactory $lFactory, IURLGenerator $url, Config $config, @@ -117,6 +120,38 @@ class Notifier implements INotifier { return $this->lFactory->get('spreed')->t('Talk'); } + /** + * @param string $objectId + * @return Room + * @throws RoomNotFoundException + */ + protected function getRoom(string $objectId): Room { + if (array_key_exists($objectId, $this->rooms)) { + if ($this->rooms[$objectId] === null) { + throw new RoomNotFoundException('Room does not exist'); + } + + return $this->rooms[$objectId]; + } + + try { + $room = $this->manager->getRoomByToken($objectId); + $this->rooms[$objectId] = $room; + return $room; + } catch (RoomNotFoundException $e) { + try { + // Before 3.2.3 the id was passed in notifications + $room = $this->manager->getRoomById((int) $objectId); + $this->rooms[$objectId] = $room; + return $room; + } catch (RoomNotFoundException $e) { + // Room does not exist + $this->rooms[$objectId] = null; + throw $e; + } + } + } + /** * @param INotification $notification * @param string $languageCode The code of the language that should be used to prepare the notification @@ -138,15 +173,10 @@ class Notifier implements INotifier { $l = $this->lFactory->get('spreed', $languageCode); try { - $room = $this->manager->getRoomByToken($notification->getObjectId()); + $room = $this->getRoom($notification->getObjectId()); } catch (RoomNotFoundException $e) { - try { - // Before 3.2.3 the id was passed in notifications - $room = $this->manager->getRoomById((int) $notification->getObjectId()); - } catch (RoomNotFoundException $e) { - // Room does not exist - throw new AlreadyProcessedException(); - } + // Room does not exist + throw new AlreadyProcessedException(); } try { -- cgit v1.2.3 From e18db3bdc8ad4c72aa4fa3a7e2b0481cfdbf0e95 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Thu, 4 Jun 2020 17:21:57 +0200 Subject: Do not query the participants for pushing call notifications We can skip the participant check when we generate push notifications. We just looped over the participants to create the notifications, they can not be removed between these 2 steps, so we can save all those queries. Signed-off-by: Joas Schilling --- lib/Notification/Notifier.php | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/Notification/Notifier.php b/lib/Notification/Notifier.php index 092cf186b..9ff13f7a6 100644 --- a/lib/Notification/Notifier.php +++ b/lib/Notification/Notifier.php @@ -179,11 +179,18 @@ class Notifier implements INotifier { throw new AlreadyProcessedException(); } - try { - $participant = $room->getParticipant($userId); - } catch (ParticipantNotFoundException $e) { - // Room does not exist - throw new AlreadyProcessedException(); + if ($this->notificationManager->isPreparingPushNotification() && $notification->getSubject() === 'call') { + // Skip the participant check when we generate push notifications + // we just looped over the participants to create the notification, + // they can not be removed between these 2 steps, but we can save + // n queries. + } else { + try { + $participant = $room->getParticipant($userId); + } catch (ParticipantNotFoundException $e) { + // Room does not exist + throw new AlreadyProcessedException(); + } } $notification -- cgit v1.2.3 From c4c2818a2a5d0b5dd65d77b21ac7e36ac5b66618 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Fri, 5 Jun 2020 09:55:28 +0200 Subject: Also cache the participant Signed-off-by: Joas Schilling --- lib/Notification/Notifier.php | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/Notification/Notifier.php b/lib/Notification/Notifier.php index 9ff13f7a6..bdacd49cb 100644 --- a/lib/Notification/Notifier.php +++ b/lib/Notification/Notifier.php @@ -75,6 +75,8 @@ class Notifier implements INotifier { /** @var Room[] */ protected $rooms = []; + /** @var Participant[][] */ + protected $participants = []; public function __construct(IFactory $lFactory, IURLGenerator $url, @@ -152,6 +154,33 @@ class Notifier implements INotifier { } } + /** + * @param Room $room + * @param string $userId + * @return Participant + * @throws ParticipantNotFoundException + */ + protected function getParticipant(Room $room, string $userId): Participant { + $roomId = $room->getId(); + if (array_key_exists($roomId, $this->participants) && array_key_exists($userId, $this->participants[$roomId])) { + if ($this->participants[$roomId][$userId] === null) { + throw new ParticipantNotFoundException('Participant does not exist'); + } + + return $this->participants[$roomId][$userId]; + } + + try { + $participant = $room->getParticipant($userId); + $this->participants[$roomId][$userId] = $participant; + return $participant; + } catch (ParticipantNotFoundException $e) { + // Participant does not exist + $this->participants[$roomId][$userId] = null; + throw $e; + } + } + /** * @param INotification $notification * @param string $languageCode The code of the language that should be used to prepare the notification @@ -186,7 +215,7 @@ class Notifier implements INotifier { // n queries. } else { try { - $participant = $room->getParticipant($userId); + $participant = $this->getParticipant($room, $userId); } catch (ParticipantNotFoundException $e) { // Room does not exist throw new AlreadyProcessedException(); -- cgit v1.2.3