Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/spreed.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorJoas Schilling <coding@schilljs.com>2022-02-27 00:21:00 +0300
committerJoas Schilling <coding@schilljs.com>2022-03-08 14:11:06 +0300
commit4348f61fdea704916273822f9603532e2ba56abe (patch)
tree262bf2f3aaa1b506425e0c8ccf7803e49ca8180a /lib
parent9a7852376ab223cca82485837efe81e8cc8be60f (diff)
Only update the last_message and last_activity once
Especially when adding multiple system messages we updated the room data way too often. Signed-off-by: Joas Schilling <coding@schilljs.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/AppInfo/Application.php4
-rw-r--r--lib/Chat/ChatManager.php18
-rw-r--r--lib/Chat/SystemMessage/Listener.php19
-rw-r--r--lib/Events/AddParticipantsEvent.php22
-rw-r--r--lib/Events/ChatEvent.php22
-rw-r--r--lib/Service/ParticipantService.php23
6 files changed, 95 insertions, 13 deletions
diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php
index 24075635b..a91636635 100644
--- a/lib/AppInfo/Application.php
+++ b/lib/AppInfo/Application.php
@@ -217,6 +217,10 @@ class Application extends App implements IBootstrap {
protected function registerRoomActivityHooks(IEventDispatcher $dispatcher): void {
$listener = function (ChatEvent $event): void {
+ if ($event->shouldSkipLastActivityUpdate()) {
+ return;
+ }
+
$room = $event->getRoom();
/** @var ITimeFactory $timeFactory */
$timeFactory = $this->getContainer()->query(ITimeFactory::class);
diff --git a/lib/Chat/ChatManager.php b/lib/Chat/ChatManager.php
index 315116835..c50cf7005 100644
--- a/lib/Chat/ChatManager.php
+++ b/lib/Chat/ChatManager.php
@@ -118,6 +118,11 @@ class ChatManager {
* @param bool $sendNotifications
* @param string|null $referenceId
* @param int|null $parentId
+ * @param bool $shouldSkipLastMessageUpdate If multiple messages will be posted
+ * (e.g. when adding multiple users to a room) we can skip the last
+ * message and last activity update until the last entry was created
+ * and then update with those values.
+ * This will replace O(n) with 1 database update.
* @return IComment
*/
public function addSystemMessage(
@@ -128,7 +133,8 @@ class ChatManager {
\DateTime $creationDateTime,
bool $sendNotifications,
?string $referenceId = null,
- ?int $parentId = null
+ ?int $parentId = null,
+ bool $shouldSkipLastMessageUpdate = false
): IComment {
$comment = $this->commentsManager->create($actorType, $actorId, 'chat', (string) $chat->getId());
$comment->setMessage($message, self::MAX_CHAT_LENGTH);
@@ -152,14 +158,16 @@ class ChatManager {
$comment->setVerb('system');
}
- $event = new ChatEvent($chat, $comment);
+ $event = new ChatEvent($chat, $comment, $shouldSkipLastMessageUpdate);
$this->dispatcher->dispatch(self::EVENT_BEFORE_SYSTEM_MESSAGE_SEND, $event);
try {
$this->commentsManager->save($comment);
- // Update last_message
- $chat->setLastMessage($comment);
- $this->unreadCountCache->clear($chat->getId() . '-');
+ if (!$shouldSkipLastMessageUpdate) {
+ // Update last_message
+ $chat->setLastMessage($comment);
+ $this->unreadCountCache->clear($chat->getId() . '-');
+ }
if ($sendNotifications) {
$this->notifier->notifyOtherParticipant($chat, $comment, []);
diff --git a/lib/Chat/SystemMessage/Listener.php b/lib/Chat/SystemMessage/Listener.php
index 0ecbd4636..2308b061b 100644
--- a/lib/Chat/SystemMessage/Listener.php
+++ b/lib/Chat/SystemMessage/Listener.php
@@ -43,6 +43,7 @@ use OCA\Talk\Share\RoomShareProvider;
use OCA\Talk\TalkSession;
use OCA\Talk\Webinary;
use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\Comments\IComment;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\EventDispatcher\IEventListener;
@@ -263,7 +264,15 @@ class Listener implements IEventListener {
|| $listener->getUserId() !== $participant['actorId']
// - has joined a listable room on their own
|| $participantType === Participant::USER) {
- $listener->sendSystemMessage($room, 'user_added', ['user' => $participant['actorId']]);
+ $comment = $listener->sendSystemMessage(
+ $room,
+ 'user_added',
+ ['user' => $participant['actorId']],
+ null,
+ $event->shouldSkipLastMessageUpdate()
+ );
+
+ $event->setLastMessage($comment);
}
}
});
@@ -379,7 +388,7 @@ class Listener implements IEventListener {
}
}
- protected function sendSystemMessage(Room $room, string $message, array $parameters = [], Participant $participant = null): void {
+ protected function sendSystemMessage(Room $room, string $message, array $parameters = [], Participant $participant = null, bool $shouldSkipLastMessageUpdate = false): IComment {
if ($participant instanceof Participant) {
$actorType = $participant->getAttendee()->getActorType();
$actorId = $participant->getAttendee()->getActorId();
@@ -408,11 +417,13 @@ class Listener implements IEventListener {
$referenceId = (string) $referenceId;
}
- $this->chatManager->addSystemMessage(
+ return $this->chatManager->addSystemMessage(
$room, $actorType, $actorId,
json_encode(['message' => $message, 'parameters' => $parameters]),
$this->timeFactory->getDateTime(), $message === 'file_shared',
- $referenceId
+ $referenceId,
+ null,
+ $shouldSkipLastMessageUpdate
);
}
diff --git a/lib/Events/AddParticipantsEvent.php b/lib/Events/AddParticipantsEvent.php
index 5d214bfb2..f05c02354 100644
--- a/lib/Events/AddParticipantsEvent.php
+++ b/lib/Events/AddParticipantsEvent.php
@@ -24,17 +24,25 @@ declare(strict_types=1);
namespace OCA\Talk\Events;
use OCA\Talk\Room;
+use OCP\Comments\IComment;
class AddParticipantsEvent extends RoomEvent {
/** @var array */
protected $participants;
+ /** @var bool */
+ protected $skipLastMessageUpdate;
+
+ /** @var IComment|null */
+ protected $lastMessage;
public function __construct(Room $room,
- array $participants) {
+ array $participants,
+ bool $skipLastMessageUpdate = false) {
parent::__construct($room);
$this->participants = $participants;
+ $this->skipLastMessageUpdate = $skipLastMessageUpdate;
}
/**
@@ -43,4 +51,16 @@ class AddParticipantsEvent extends RoomEvent {
public function getParticipants(): array {
return $this->participants;
}
+
+ public function shouldSkipLastMessageUpdate(): bool {
+ return $this->skipLastMessageUpdate;
+ }
+
+ public function setLastMessage(IComment $lastMessage): void {
+ $this->lastMessage = $lastMessage;
+ }
+
+ public function getLastMessage(): ?IComment {
+ return $this->lastMessage;
+ }
}
diff --git a/lib/Events/ChatEvent.php b/lib/Events/ChatEvent.php
index 2a9e548e2..1f552f7d7 100644
--- a/lib/Events/ChatEvent.php
+++ b/lib/Events/ChatEvent.php
@@ -31,13 +31,33 @@ class ChatEvent extends RoomEvent {
/** @var IComment */
protected $comment;
+ /** @var bool */
+ protected $skipLastActivityUpdate;
- public function __construct(Room $room, IComment $comment) {
+ public function __construct(Room $room,
+ IComment $comment,
+ bool $skipLastActivityUpdate = false) {
parent::__construct($room);
$this->comment = $comment;
+ $this->skipLastActivityUpdate = $skipLastActivityUpdate;
}
public function getComment(): IComment {
return $this->comment;
}
+
+ /**
+ * If multiple messages will be posted (e.g. when adding multiple users to a room)
+ * we can skip the last message and last activity update until the last entry
+ * was created and then update with those values.
+ * This will replace O(n) with 1 database update.
+ *
+ * A ChatManager::EVENT_AFTER_MULTIPLE_SYSTEM_MESSAGE_SEND will be triggered
+ * as a final event when all messages have been created.
+ *
+ * @return bool
+ */
+ public function shouldSkipLastActivityUpdate(): bool {
+ return $this->skipLastActivityUpdate;
+ }
}
diff --git a/lib/Service/ParticipantService.php b/lib/Service/ParticipantService.php
index 960330cee..c02a4910a 100644
--- a/lib/Service/ParticipantService.php
+++ b/lib/Service/ParticipantService.php
@@ -59,6 +59,7 @@ use OCP\Comments\IComment;
use OCP\DB\Exception;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\EventDispatcher\IEventDispatcher;
+use OCP\ICacheFactory;
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\IGroup;
@@ -94,6 +95,8 @@ class ParticipantService {
private $notifications;
/** @var ITimeFactory */
private $timeFactory;
+ /** @var ICacheFactory */
+ private $cacheFactory;
public function __construct(IConfig $serverConfig,
Config $talkConfig,
@@ -107,7 +110,8 @@ class ParticipantService {
IGroupManager $groupManager,
MembershipService $membershipService,
Notifications $notifications,
- ITimeFactory $timeFactory) {
+ ITimeFactory $timeFactory,
+ ICacheFactory $cacheFactory) {
$this->serverConfig = $serverConfig;
$this->talkConfig = $talkConfig;
$this->attendeeMapper = $attendeeMapper;
@@ -120,6 +124,7 @@ class ParticipantService {
$this->groupManager = $groupManager;
$this->membershipService = $membershipService;
$this->timeFactory = $timeFactory;
+ $this->cacheFactory = $cacheFactory;
$this->notifications = $notifications;
}
@@ -367,7 +372,7 @@ class ParticipantService {
if (empty($participants)) {
return;
}
- $event = new AddParticipantsEvent($room, $participants);
+ $event = new AddParticipantsEvent($room, $participants, true);
$this->dispatcher->dispatch(Room::EVENT_BEFORE_USERS_ADD, $event);
$lastMessage = 0;
@@ -426,9 +431,23 @@ class ParticipantService {
$this->dispatcher->dispatchTyped($attendeeEvent);
$this->dispatcher->dispatch(Room::EVENT_AFTER_USERS_ADD, $event);
+
+ $lastMessage = $event->getLastMessage();
+ if ($lastMessage instanceof IComment) {
+ $this->updateRoomLastMessage($room, $lastMessage);
+ }
}
}
+ protected function updateRoomLastMessage(Room $room, IComment $message): void {
+ $room->setLastMessage($message);
+ $room->setLastActivity($message->getCreationDateTime());
+ $lastMessageCache = $this->cacheFactory->createDistributed('talk/lastmsgid');
+ $lastMessageCache->remove($room->getToken());
+ $unreadCountCache = $this->cacheFactory->createDistributed('talk/unreadcount');
+ $unreadCountCache->clear($room->getId() . '-');
+ }
+
public function getHighestPermissionAttendee(Room $room): ?Attendee {
try {
$roomOwners = $this->attendeeMapper->getActorsByParticipantTypes($room->getId(), [Participant::OWNER]);