fix(TreeMapper#getChildren): Add more aggressive per-layer caching

Signed-off-by: Marcel Klehr <mklehr@gmx.net>
This commit is contained in:
Marcel Klehr 2024-01-03 13:57:22 +01:00
parent c2213b9e09
commit 61d9750b9f
2 changed files with 30 additions and 18 deletions

View File

@ -805,24 +805,31 @@ class TreeMapper extends QBMapper {
if ($children !== null) {
return $children;
}
$qb = $this->getChildrenQuery[self::TYPE_BOOKMARK];
$this->selectFromType(self::TYPE_BOOKMARK, ['t.index', 't.type'], $qb);
$qb->setParameter('parent_folder', $folderId);
$childBookmarks = $qb->execute()->fetchAll();
$qb = $this->getChildrenQuery[self::TYPE_FOLDER];
$this->selectFromType(self::TYPE_FOLDER, ['t.index', 't.type'], $qb);
$qb->setParameter('parent_folder', $folderId);
$childFolders = $qb->execute()->fetchAll();
$children = $this->treeCache->get(TreeCacheManager::CATEGORY_CHILDREN_LAYER, TreeMapper::TYPE_FOLDER, $folderId);
$qb = $this->getChildrenQuery[self::TYPE_SHARE];
$this->selectFromType(self::TYPE_SHARE, ['t.index', 't.type'], $qb);
$qb->setParameter('parent_folder', $folderId);
$childShares = $qb->execute()->fetchAll();
if ($children === null) {
$qb = $this->getChildrenQuery[self::TYPE_BOOKMARK];
$this->selectFromType(self::TYPE_BOOKMARK, ['t.index', 't.type'], $qb);
$qb->setParameter('parent_folder', $folderId);
$childBookmarks = $qb->execute()->fetchAll();
$children = array_merge($childBookmarks, $childFolders, $childShares);
$indices = array_column($children, 'index');
array_multisort($indices, $children);
$qb = $this->getChildrenQuery[self::TYPE_FOLDER];
$this->selectFromType(self::TYPE_FOLDER, ['t.index', 't.type'], $qb);
$qb->setParameter('parent_folder', $folderId);
$childFolders = $qb->execute()->fetchAll();
$qb = $this->getChildrenQuery[self::TYPE_SHARE];
$this->selectFromType(self::TYPE_SHARE, ['t.index', 't.type'], $qb);
$qb->setParameter('parent_folder', $folderId);
$childShares = $qb->execute()->fetchAll();
$children = array_merge($childBookmarks, $childFolders, $childShares);
$indices = array_column($children, 'index');
array_multisort($indices, $children);
$this->treeCache->set(TreeCacheManager::CATEGORY_CHILDREN_LAYER, TreeMapper::TYPE_FOLDER, $folderId, $children);
}
$children = array_map(function ($child) use ($layers) {
$item = ['type' => $child['type'], 'id' => (int)$child['id'], 'title' => $child['title'], 'userId' => $child['user_id']];

View File

@ -30,6 +30,7 @@ class TreeCacheManager implements IEventListener {
public const CATEGORY_SUBFOLDERS = 'subFolders';
public const CATEGORY_FOLDERCOUNT = 'folderCount';
public const CATEGORY_CHILDREN = 'children';
public const CATEGORY_CHILDREN_LAYER = 'children_layer';
public const CATEGORY_CHILDORDER = 'childOrder';
/**
@ -87,6 +88,7 @@ class TreeCacheManager implements IEventListener {
$this->caches[self::CATEGORY_SUBFOLDERS] = $cacheFactory->createLocal('bookmarks:'.self::CATEGORY_SUBFOLDERS);
$this->caches[self::CATEGORY_FOLDERCOUNT] = $cacheFactory->createLocal('bookmarks:'.self::CATEGORY_FOLDERCOUNT);
$this->caches[self::CATEGORY_CHILDREN] = $cacheFactory->createLocal('bookmarks:'.self::CATEGORY_CHILDREN);
$this->caches[self::CATEGORY_CHILDREN_LAYER] = $cacheFactory->createLocal('bookmarks:'.self::CATEGORY_CHILDREN_LAYER);
$this->caches[self::CATEGORY_CHILDORDER] = $cacheFactory->createLocal('bookmarks:'.self::CATEGORY_CHILDORDER);
$this->appContainer = $appContainer;
$this->tagMapper = $tagMapper;
@ -133,9 +135,12 @@ class TreeCacheManager implements IEventListener {
* @param string $type
* @param int $id
*/
public function remove(string $type, int $id): void {
public function remove(string $type, int $id, array $previousFolders): void {
$key = $this->getCacheKey($type, $id);
foreach ($this->caches as $cache) {
foreach ($this->caches as $type => $cache) {
if (count($previousFolders) !== 0 && ($type === self::CATEGORY_CHILDORDER || $type === self::CATEGORY_CHILDREN_LAYER)) {
continue;
}
$cache->remove($key);
}
}
@ -149,7 +154,7 @@ class TreeCacheManager implements IEventListener {
// In case we have run into a folder loop
return;
}
$this->remove(TreeMapper::TYPE_FOLDER, $folderId);
$this->remove(TreeMapper::TYPE_FOLDER, $folderId, $previousFolders);
$previousFolders[] = $folderId;
// Invalidate parent