perf: Enrich calls in combined sql queries
Signed-off-by: Julius Härtl <jus@bitgrid.net>
This commit is contained in:
@@ -28,11 +28,13 @@ namespace OCA\Deck\Service;
|
|||||||
|
|
||||||
use OCA\Deck\Activity\ActivityManager;
|
use OCA\Deck\Activity\ActivityManager;
|
||||||
use OCA\Deck\Activity\ChangeSet;
|
use OCA\Deck\Activity\ChangeSet;
|
||||||
|
use OCA\Deck\Db\Assignment;
|
||||||
use OCA\Deck\Db\AssignmentMapper;
|
use OCA\Deck\Db\AssignmentMapper;
|
||||||
use OCA\Deck\Db\Card;
|
use OCA\Deck\Db\Card;
|
||||||
use OCA\Deck\Db\CardMapper;
|
use OCA\Deck\Db\CardMapper;
|
||||||
use OCA\Deck\Db\Acl;
|
use OCA\Deck\Db\Acl;
|
||||||
use OCA\Deck\Db\ChangeHelper;
|
use OCA\Deck\Db\ChangeHelper;
|
||||||
|
use OCA\Deck\Db\Label;
|
||||||
use OCA\Deck\Db\StackMapper;
|
use OCA\Deck\Db\StackMapper;
|
||||||
use OCA\Deck\Event\CardCreatedEvent;
|
use OCA\Deck\Event\CardCreatedEvent;
|
||||||
use OCA\Deck\Event\CardDeletedEvent;
|
use OCA\Deck\Event\CardDeletedEvent;
|
||||||
@@ -114,32 +116,52 @@ class CardService {
|
|||||||
$this->cardServiceValidator = $cardServiceValidator;
|
$this->cardServiceValidator = $cardServiceValidator;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function enrich($card) {
|
public function enrichCards($cards) {
|
||||||
$cardId = $card->getId();
|
|
||||||
$this->cardMapper->mapOwner($card);
|
|
||||||
$card->setAssignedUsers($this->assignedUsersMapper->findAll($cardId));
|
|
||||||
$card->setLabels($this->labelMapper->findAssignedLabelsForCard($cardId));
|
|
||||||
$card->setAttachmentCount($this->attachmentService->count($cardId));
|
|
||||||
$user = $this->userManager->get($this->currentUser);
|
$user = $this->userManager->get($this->currentUser);
|
||||||
$lastRead = $this->commentsManager->getReadMark('deckCard', (string)$card->getId(), $user);
|
|
||||||
$countUnreadComments = $this->commentsManager->getNumberOfCommentsForObject('deckCard', (string)$card->getId(), $lastRead);
|
|
||||||
$countComments = $this->commentsManager->getNumberOfCommentsForObject('deckCard', (string)$card->getId());
|
|
||||||
$card->setCommentsUnread($countUnreadComments);
|
|
||||||
$card->setCommentsCount($countComments);
|
|
||||||
|
|
||||||
$stack = $this->stackMapper->find($card->getStackId());
|
$cardIds = array_map(function (Card $card) {
|
||||||
$board = $this->boardService->find($stack->getBoardId());
|
// Everything done in here might be heavy as it is executed for every card
|
||||||
$card->setRelatedStack($stack);
|
$cardId = $card->getId();
|
||||||
$card->setRelatedBoard($board);
|
$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());
|
||||||
|
$board = $this->boardService->find($stack->getBoardId(), false);
|
||||||
|
$card->setRelatedStack($stack);
|
||||||
|
$card->setRelatedBoard($board);
|
||||||
|
|
||||||
|
return $card->getId();
|
||||||
|
}, $cards);
|
||||||
|
|
||||||
|
$assignedLabels = $this->labelMapper->findAssignedLabelsForCards($cardIds);
|
||||||
|
$assignedUsers = $this->assignedUsersMapper->findIn($cardIds);
|
||||||
|
|
||||||
|
foreach ($cards as $card) {
|
||||||
|
$cardLabels = array_filter($assignedLabels, function (Label $label) use ($card) {
|
||||||
|
return $label->getCardId() === $card->getId();
|
||||||
|
});
|
||||||
|
$cardAssignedUsers = array_filter($assignedUsers, function (Assignment $label) use ($card) {
|
||||||
|
return $label->getCardId() === $card->getId();
|
||||||
|
});
|
||||||
|
$card->setLabels($cardLabels);
|
||||||
|
$card->setAssignedUsers($cardAssignedUsers);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $cards;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function fetchDeleted($boardId) {
|
public function fetchDeleted($boardId) {
|
||||||
$this->cardServiceValidator->check(compact('boardId'));
|
$this->cardServiceValidator->check(compact('boardId'));
|
||||||
$this->permissionService->checkPermission($this->boardMapper, $boardId, Acl::PERMISSION_READ);
|
$this->permissionService->checkPermission($this->boardMapper, $boardId, Acl::PERMISSION_READ);
|
||||||
$cards = $this->cardMapper->findDeleted($boardId);
|
$cards = $this->cardMapper->findDeleted($boardId);
|
||||||
foreach ($cards as $card) {
|
$this->enrichCards($cards);
|
||||||
$this->enrich($card);
|
|
||||||
}
|
|
||||||
return $cards;
|
return $cards;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,7 +184,7 @@ class CardService {
|
|||||||
}
|
}
|
||||||
$card->setAssignedUsers($assignedUsers);
|
$card->setAssignedUsers($assignedUsers);
|
||||||
$card->setAttachments($attachments);
|
$card->setAttachments($attachments);
|
||||||
$this->enrich($card);
|
$this->enrichCards([$card]);
|
||||||
return $card;
|
return $card;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,9 +196,7 @@ class CardService {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
$cards = $this->cardMapper->findCalendarEntries($boardId);
|
$cards = $this->cardMapper->findCalendarEntries($boardId);
|
||||||
foreach ($cards as $card) {
|
$this->enrichCards($cards);
|
||||||
$this->enrich($card);
|
|
||||||
}
|
|
||||||
return $cards;
|
return $cards;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,8 +35,10 @@ use OCP\Comments\ICommentsManager;
|
|||||||
use OCA\Deck\Db\BoardMapper;
|
use OCA\Deck\Db\BoardMapper;
|
||||||
use OCA\Deck\Db\LabelMapper;
|
use OCA\Deck\Db\LabelMapper;
|
||||||
use OCP\IUserManager;
|
use OCP\IUserManager;
|
||||||
|
use OCP\IUserSession;
|
||||||
|
|
||||||
class OverviewService {
|
class OverviewService {
|
||||||
|
private CardService $cardService;
|
||||||
private BoardMapper $boardMapper;
|
private BoardMapper $boardMapper;
|
||||||
private LabelMapper $labelMapper;
|
private LabelMapper $labelMapper;
|
||||||
private CardMapper $cardMapper;
|
private CardMapper $cardMapper;
|
||||||
@@ -46,6 +48,7 @@ class OverviewService {
|
|||||||
private AttachmentService $attachmentService;
|
private AttachmentService $attachmentService;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
|
CardService $cardService,
|
||||||
BoardMapper $boardMapper,
|
BoardMapper $boardMapper,
|
||||||
LabelMapper $labelMapper,
|
LabelMapper $labelMapper,
|
||||||
CardMapper $cardMapper,
|
CardMapper $cardMapper,
|
||||||
@@ -54,6 +57,7 @@ class OverviewService {
|
|||||||
ICommentsManager $commentsManager,
|
ICommentsManager $commentsManager,
|
||||||
AttachmentService $attachmentService
|
AttachmentService $attachmentService
|
||||||
) {
|
) {
|
||||||
|
$this->cardService = $cardService;
|
||||||
$this->boardMapper = $boardMapper;
|
$this->boardMapper = $boardMapper;
|
||||||
$this->labelMapper = $labelMapper;
|
$this->labelMapper = $labelMapper;
|
||||||
$this->cardMapper = $cardMapper;
|
$this->cardMapper = $cardMapper;
|
||||||
@@ -63,32 +67,15 @@ class OverviewService {
|
|||||||
$this->attachmentService = $attachmentService;
|
$this->attachmentService = $attachmentService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function enrich(Card $card, string $userId): void {
|
|
||||||
$cardId = $card->getId();
|
|
||||||
|
|
||||||
$this->cardMapper->mapOwner($card);
|
|
||||||
$card->setAssignedUsers($this->assignedUsersMapper->findAll($cardId));
|
|
||||||
$card->setLabels($this->labelMapper->findAssignedLabelsForCard($cardId));
|
|
||||||
$card->setAttachmentCount($this->attachmentService->count($cardId));
|
|
||||||
|
|
||||||
$user = $this->userManager->get($userId);
|
|
||||||
if ($user !== null) {
|
|
||||||
$lastRead = $this->commentsManager->getReadMark('deckCard', (string)$card->getId(), $user);
|
|
||||||
$count = $this->commentsManager->getNumberOfCommentsForObject('deckCard', (string)$card->getId(), $lastRead);
|
|
||||||
$card->setCommentsUnread($count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function findAllWithDue(string $userId): array {
|
public function findAllWithDue(string $userId): array {
|
||||||
$userBoards = $this->boardMapper->findAllForUser($userId);
|
$userBoards = $this->boardMapper->findAllForUser($userId);
|
||||||
$allDueCards = [];
|
$allDueCards = [];
|
||||||
foreach ($userBoards as $userBoard) {
|
foreach ($userBoards as $userBoard) {
|
||||||
$allDueCards[] = array_map(function ($card) use ($userBoard, $userId) {
|
$allDueCards[] = array_map(function ($card) use ($userBoard, $userId) {
|
||||||
$this->enrich($card, $userId);
|
|
||||||
return (new CardDetails($card, $userBoard))->jsonSerialize();
|
return (new CardDetails($card, $userBoard))->jsonSerialize();
|
||||||
}, $this->cardMapper->findAllWithDue($userBoard->getId()));
|
}, $this->cardMapper->findAllWithDue($userBoard->getId()));
|
||||||
}
|
}
|
||||||
return array_merge(...$allDueCards);
|
return $this->cardService->enrichCards(array_merge(...$allDueCards));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function findUpcomingCards(string $userId): array {
|
public function findUpcomingCards(string $userId): array {
|
||||||
@@ -103,26 +90,29 @@ class OverviewService {
|
|||||||
$cards = $this->cardMapper->findToMeOrNotAssignedCards($userBoard->getId(), $userId);
|
$cards = $this->cardMapper->findToMeOrNotAssignedCards($userBoard->getId(), $userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($cards as $card) {
|
$foundCards[] = $cards;
|
||||||
$this->enrich($card, $userId);
|
}
|
||||||
$diffDays = $card->getDaysUntilDue();
|
|
||||||
|
|
||||||
$key = 'later';
|
$foundCards = array_merge(...$foundCards);
|
||||||
if ($diffDays === null) {
|
$this->cardService->enrichCards($foundCards);
|
||||||
$key = 'nodue';
|
foreach ($foundCards as $card) {
|
||||||
} elseif ($diffDays < 0) {
|
$diffDays = $card->getDaysUntilDue();
|
||||||
$key = 'overdue';
|
|
||||||
} elseif ($diffDays === 0) {
|
|
||||||
$key = 'today';
|
|
||||||
} elseif ($diffDays === 1) {
|
|
||||||
$key = 'tomorrow';
|
|
||||||
} elseif ($diffDays <= 7) {
|
|
||||||
$key = 'nextSevenDays';
|
|
||||||
}
|
|
||||||
|
|
||||||
$card = (new CardDetails($card, $userBoard));
|
$key = 'later';
|
||||||
$overview[$key][] = $card->jsonSerialize();
|
if ($diffDays === null) {
|
||||||
|
$key = 'nodue';
|
||||||
|
} elseif ($diffDays < 0) {
|
||||||
|
$key = 'overdue';
|
||||||
|
} elseif ($diffDays === 0) {
|
||||||
|
$key = 'today';
|
||||||
|
} elseif ($diffDays === 1) {
|
||||||
|
$key = 'tomorrow';
|
||||||
|
} elseif ($diffDays <= 7) {
|
||||||
|
$key = 'nextSevenDays';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$card = (new CardDetails($card, $userBoard));
|
||||||
|
$overview[$key][] = $card->jsonSerialize();
|
||||||
}
|
}
|
||||||
return $overview;
|
return $overview;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,10 +83,7 @@ class SearchService {
|
|||||||
$matchedCards = $this->cardMapper->search($boardIds, $this->filterStringParser->parse($term), $limit, $cursor);
|
$matchedCards = $this->cardMapper->search($boardIds, $this->filterStringParser->parse($term), $limit, $cursor);
|
||||||
|
|
||||||
$self = $this;
|
$self = $this;
|
||||||
return array_map(function (Card $card) use ($self) {
|
return $this->cardService->enrichCards($matchedCards);
|
||||||
$self->cardService->enrich($card);
|
|
||||||
return $card;
|
|
||||||
}, $matchedCards);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function searchBoards(string $term, ?int $limit, ?int $cursor): array {
|
public function searchBoards(string $term, ?int $limit, ?int $cursor): array {
|
||||||
@@ -117,7 +114,8 @@ class SearchService {
|
|||||||
$comment = $this->commentsManager->get($cardRow['comment_id']);
|
$comment = $this->commentsManager->get($cardRow['comment_id']);
|
||||||
unset($cardRow['comment_id']);
|
unset($cardRow['comment_id']);
|
||||||
$card = Card::fromRow($cardRow);
|
$card = Card::fromRow($cardRow);
|
||||||
$self->cardService->enrich($card);
|
// TODO: Only perform one enrich call here
|
||||||
|
$self->cardService->enrichCards([$card]);
|
||||||
$user = $this->userManager->get($comment->getActorId());
|
$user = $this->userManager->get($comment->getActorId());
|
||||||
$displayName = $user ? $user->getDisplayName() : '';
|
$displayName = $user ? $user->getDisplayName() : '';
|
||||||
return new CommentSearchResultEntry($comment->getId(), $comment->getMessage(), $displayName, $card, $this->urlGenerator, $this->l10n);
|
return new CommentSearchResultEntry($comment->getId(), $comment->getMessage(), $displayName, $card, $this->urlGenerator, $this->l10n);
|
||||||
|
|||||||
@@ -94,9 +94,9 @@ class StackService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->cardService->enrichCards($cards);
|
||||||
$cards = array_map(
|
$cards = array_map(
|
||||||
function (Card $card): CardDetails {
|
function (Card $card): CardDetails {
|
||||||
$this->cardService->enrich($card);
|
|
||||||
return new CardDetails($card);
|
return new CardDetails($card);
|
||||||
},
|
},
|
||||||
$cards
|
$cards
|
||||||
|
|||||||
Reference in New Issue
Block a user