From ce5faf05abf410dfdeb0582d22d50934b3169c31 Mon Sep 17 00:00:00 2001 From: Carl Schwan Date: Wed, 13 Aug 2025 14:53:43 +0200 Subject: [PATCH] perf(stack): Optimize fetching all cards from a stack - Don't fetch stack, if we already know it - fetch all comments at the same time, instead of for each card Signed-off-by: Carl Schwan --- lib/Service/CardService.php | 39 ++++++++++++++++++++++++++---------- lib/Service/StackService.php | 2 +- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/lib/Service/CardService.php b/lib/Service/CardService.php index 8fad26447..02f81d5ed 100644 --- a/lib/Service/CardService.php +++ b/lib/Service/CardService.php @@ -19,6 +19,7 @@ use OCA\Deck\Db\ChangeHelper; use OCA\Deck\Db\Label; use OCA\Deck\Db\LabelMapper; +use OCA\Deck\Db\Stack; use OCA\Deck\Db\StackMapper; use OCA\Deck\Event\CardCreatedEvent; use OCA\Deck\Event\CardDeletedEvent; @@ -64,31 +65,47 @@ public function __construct( ) { } - public function enrichCards($cards) { + /** + * @param Card[] $cards + * @return CardDetails[] + */ + public function enrichCards(array $cards, Stack $stack = null): array { + if (!$cards) { + return []; + } + $user = $this->userManager->get($this->userId); - $cardIds = array_map(function (Card $card) use ($user) { + $cardIds = array_map(function (Card $card) use ($user, $stack) { // Everything done in here might be heavy as it is executed for every card $cardId = $card->getId(); $this->cardMapper->mapOwner($card); $card->setAttachmentCount($this->attachmentService->count($cardId)); - // TODO We should find a better way just to get the comment count so we can save 1-3 queries per card here - $countComments = $this->commentsManager->getNumberOfCommentsForObject('deckCard', (string)$card->getId()); - $lastRead = $countComments > 0 ? $this->commentsManager->getReadMark('deckCard', (string)$card->getId(), $user) : null; - $countUnreadComments = $lastRead ? $this->commentsManager->getNumberOfCommentsForObject('deckCard', (string)$card->getId(), $lastRead) : 0; - $card->setCommentsUnread($countUnreadComments); - $card->setCommentsCount($countComments); - - $stack = $this->stackMapper->find($card->getStackId()); + if ($stack === null) { + $stack = $this->stackMapper->find($card->getStackId()); + } $board = $this->boardService->find($stack->getBoardId(), false); $card->setRelatedStack($stack); $card->setRelatedBoard($board); - return $card->getId(); + return $cardId; }, $cards); + $commentsCountPerCardId = $this->commentsManager->getNumberOfCommentsForObjects('deckCard', $cardIds); + $unreadCommentsCountPerCardId = $this->commentsManager->getNumberOfUnreadCommentsForObjects('deckCard', $cardIds, $user); + + foreach ($commentsCountPerCardId as $cardId => $commentCounts) { + foreach ($cards as $card) { + if ($card->getId() === $cardId) { + $card->setCommentsUnread($unreadCommentsCountPerCardId[$cardId]); + $card->setCommentsCount($commentCounts); + break; + } + } + } + $assignedLabels = $this->labelMapper->findAssignedLabelsForCards($cardIds); $assignedUsers = $this->assignedUsersMapper->findIn($cardIds); diff --git a/lib/Service/StackService.php b/lib/Service/StackService.php index 8495d9d92..fab359227 100644 --- a/lib/Service/StackService.php +++ b/lib/Service/StackService.php @@ -82,7 +82,7 @@ private function enrichStackWithCards($stack, $since = -1) { return; } - $stack->setCards($this->cardService->enrichCards($cards)); + $stack->setCards($this->cardService->enrichCards($cards, $stack)); } private function enrichStacksWithCards($stacks, $since = -1) {