From 7c4ceb444cb22f519cd30af5cd22304b960c8818 Mon Sep 17 00:00:00 2001 From: Anna Larch Date: Thu, 3 Nov 2022 12:51:29 +0100 Subject: Add group display name cache Signed-off-by: Anna Larch --- lib/private/Group/DisplayNameCache.php | 87 ++++++++++++++++++++++++++++++++++ lib/private/Group/Group.php | 2 + lib/private/Group/Manager.php | 17 ++++++- 3 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 lib/private/Group/DisplayNameCache.php (limited to 'lib/private/Group') diff --git a/lib/private/Group/DisplayNameCache.php b/lib/private/Group/DisplayNameCache.php new file mode 100644 index 00000000000..d724b6caf0e --- /dev/null +++ b/lib/private/Group/DisplayNameCache.php @@ -0,0 +1,87 @@ + + * @author Anna Larch + * + * @license AGPL-3.0-or-later + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see + * + */ + + +namespace OC\Group; + +use OCP\Cache\CappedMemoryCache; +use OCP\EventDispatcher\Event; +use OCP\EventDispatcher\IEventListener; +use OCP\Group\Events\GroupChangedEvent; +use OCP\ICache; +use OCP\ICacheFactory; +use OCP\IGroupManager; + +/** + * Class that cache the relation Group ID -> Display name + * + * This saves fetching the group from the backend for "just" the display name + */ +class DisplayNameCache implements IEventListener { + private CappedMemoryCache $cache; + private ICache $memCache; + private IGroupManager $groupManager; + + public function __construct(ICacheFactory $cacheFactory, IGroupManager $groupManager) { + $this->cache = new CappedMemoryCache(); + $this->memCache = $cacheFactory->createDistributed('groupDisplayNameMappingCache'); + $this->groupManager = $groupManager; + } + + public function getDisplayName(string $groupId): ?string { + if (isset($this->cache[$groupId])) { + return $this->cache[$groupId]; + } + $displayName = $this->memCache->get($groupId); + if ($displayName) { + $this->cache[$groupId] = $displayName; + return $displayName; + } + + $group = $this->groupManager->get($groupId); + if ($group) { + $displayName = $group->getDisplayName(); + } else { + $displayName = null; + } + $this->cache[$groupId] = $displayName; + $this->memCache->set($groupId, $displayName, 60 * 10); // 10 minutes + + return $displayName; + } + + public function clear(): void { + $this->cache = new CappedMemoryCache(); + $this->memCache->clear(); + } + + public function handle(Event $event): void { + if ($event instanceof GroupChangedEvent && $event->getFeature() === 'displayName') { + $groupId = $event->getGroup()->getGID(); + $newDisplayName = $event->getValue(); + $this->cache[$groupId] = $newDisplayName; + $this->memCache->set($groupId, $newDisplayName, 60 * 10); // 10 minutes + } + } +} diff --git a/lib/private/Group/Group.php b/lib/private/Group/Group.php index 2ef4d2ee23f..ae70a611e4e 100644 --- a/lib/private/Group/Group.php +++ b/lib/private/Group/Group.php @@ -38,6 +38,7 @@ use OCP\Group\Backend\IGetDisplayNameBackend; use OCP\Group\Backend\IHideFromCollaborationBackend; use OCP\Group\Backend\INamedBackend; use OCP\Group\Backend\ISetDisplayNameBackend; +use OCP\Group\Events\GroupChangedEvent; use OCP\GroupInterface; use OCP\IGroup; use OCP\IUser; @@ -112,6 +113,7 @@ class Group implements IGroup { if (($backend instanceof ISetDisplayNameBackend) && $backend->setDisplayName($this->gid, $displayName)) { $this->displayName = $displayName; + $this->dispatcher->dispatch(new GroupChangedEvent($this, 'displayName', $displayName, '')); return true; } } diff --git a/lib/private/Group/Manager.php b/lib/private/Group/Manager.php index 28f7a400b41..b718afa5168 100644 --- a/lib/private/Group/Manager.php +++ b/lib/private/Group/Manager.php @@ -42,6 +42,7 @@ namespace OC\Group; use OC\Hooks\PublicEmitter; use OCP\EventDispatcher\IEventDispatcher; use OCP\GroupInterface; +use OCP\ICacheFactory; use OCP\IGroup; use OCP\IGroupManager; use OCP\IUser; @@ -82,12 +83,16 @@ class Manager extends PublicEmitter implements IGroupManager { /** @var \OC\SubAdmin */ private $subAdmin = null; + private DisplayNameCache $displayNameCache; + public function __construct(\OC\User\Manager $userManager, EventDispatcherInterface $dispatcher, - LoggerInterface $logger) { + LoggerInterface $logger, + ICacheFactory $cacheFactory) { $this->userManager = $userManager; $this->dispatcher = $dispatcher; $this->logger = $logger; + $this->displayNameCache = new DisplayNameCache($cacheFactory, $this); $cachedGroups = &$this->cachedGroups; $cachedUserGroups = &$this->cachedUserGroups; @@ -338,6 +343,14 @@ class Manager extends PublicEmitter implements IGroupManager { return $this->cachedUserGroups[$uid]; } + /** + * @param string $groupId + * @return ?string + */ + public function getDisplayName(string $groupId): ?string { + return $this->displayNameCache->getDisplayName($groupId); + } + /** * get an array of groupid and displayName for a user * @@ -346,7 +359,7 @@ class Manager extends PublicEmitter implements IGroupManager { */ public function getUserGroupNames(IUser $user) { return array_map(function ($group) { - return ['displayName' => $group->getDisplayName()]; + return ['displayName' => $this->displayNameCache->getDisplayName($group->getGID())]; }, $this->getUserGroups($user)); } -- cgit v1.2.3