Browse Source

cache cloud id data in CloudIdManager

Signed-off-by: Robin Appelman <robin@icewind.nl>
tags/v25.0.0beta4
Robin Appelman 1 year ago
parent
commit
d3743392e0
No account linked to committer's email address
2 changed files with 80 additions and 7 deletions
  1. 73
    6
      lib/private/Federation/CloudIdManager.php
  2. 7
    1
      lib/private/Server.php

+ 73
- 6
lib/private/Federation/CloudIdManager.php View File

@@ -30,11 +30,17 @@ declare(strict_types=1);
*/
namespace OC\Federation;

use OCA\DAV\Events\CardUpdatedEvent;
use OCP\Contacts\IManager;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Federation\ICloudId;
use OCP\Federation\ICloudIdManager;
use OCP\ICache;
use OCP\ICacheFactory;
use OCP\IURLGenerator;
use OCP\IUserManager;
use OCP\User\Events\UserChangedEvent;

class CloudIdManager implements ICloudIdManager {
/** @var IManager */
@@ -43,11 +49,48 @@ class CloudIdManager implements ICloudIdManager {
private $urlGenerator;
/** @var IUserManager */
private $userManager;

public function __construct(IManager $contactsManager, IURLGenerator $urlGenerator, IUserManager $userManager) {
private ICache $memCache;
/** @var array[] */
private array $cache = [];

public function __construct(
IManager $contactsManager,
IURLGenerator $urlGenerator,
IUserManager $userManager,
ICacheFactory $cacheFactory,
IEventDispatcher $eventDispatcher
) {
$this->contactsManager = $contactsManager;
$this->urlGenerator = $urlGenerator;
$this->userManager = $userManager;
$this->memCache = $cacheFactory->createDistributed('cloud_id_');
$eventDispatcher->addListener(UserChangedEvent::class, [$this, 'handleUserEvent']);
$eventDispatcher->addListener(CardUpdatedEvent::class, [$this, 'handleCardEvent']);
}

public function handleUserEvent(Event $event): void {
if ($event instanceof UserChangedEvent && $event->getFeature() === 'displayName') {
$userId = $event->getUser()->getUID();
$key = $userId . '@local';
unset($this->cache[$key]);
$this->memCache->remove($key);
}
}

public function handleCardEvent(Event $event): void {
if ($event instanceof CardUpdatedEvent) {
$data = $event->getCardData()['carddata'];
foreach (explode("\r\n", $data) as $line) {
if (strpos($line, "CLOUD;") === 0) {
$parts = explode(':', $line, 2);
if (isset($parts[1])) {
$key = $parts[1];
unset($this->cache[$key]);
$this->memCache->remove($key);
}
}
}
}
}

/**
@@ -120,18 +163,42 @@ class CloudIdManager implements ICloudIdManager {
* @return CloudId
*/
public function getCloudId(string $user, ?string $remote): ICloudId {
if ($remote === null) {
$isLocal = $remote === null;
if ($isLocal) {
$remote = rtrim($this->removeProtocolFromUrl($this->urlGenerator->getAbsoluteURL('/')), '/');
$fixedRemote = $this->fixRemoteURL($remote);
$localUser = $this->userManager->get($user);
$displayName = !is_null($localUser) ? $localUser->getDisplayName() : '';
$host = $fixedRemote;
} else {
// TODO check what the correct url is for remote (asking the remote)
// note that for remote id's we don't strip the protocol for the remote we use to construct the CloudId
// this way if a user has an explicit non-https cloud id this will be preserved
// we do still use the version without protocol for looking up the display name
$fixedRemote = $this->fixRemoteURL($remote);
$host = $this->removeProtocolFromUrl($fixedRemote);
}

$key = $user . '@' . ($isLocal ? 'local' : $host);
$cached = $this->cache[$key] ?? $this->memCache->get($key);
if ($cached) {
$this->cache[$key] = $cached; // put items from memcache into local cache
return new CloudId($cached['id'], $cached['user'], $cached['remote'], $cached['displayName']);
}

if ($isLocal) {
$localUser = $this->userManager->get($user);
$displayName = $localUser ? $localUser->getDisplayName() : '';
} else {
$displayName = $this->getDisplayNameFromContact($user . '@' . $host);
}
$id = $user . '@' . $remote;

$data = [
'id' => $id,
'user' => $user,
'remote' => $fixedRemote,
'displayName' => $displayName,
];
$this->cache[$key] = $data;
$this->memCache->set($key, $data, 15 * 60);
return new CloudId($id, $user, $fixedRemote, $displayName);
}


+ 7
- 1
lib/private/Server.php View File

@@ -1361,7 +1361,13 @@ class Server extends ServerContainer implements IServerContainer {
});

$this->registerService(ICloudIdManager::class, function (ContainerInterface $c) {
return new CloudIdManager($c->get(\OCP\Contacts\IManager::class), $c->get(IURLGenerator::class), $c->get(IUserManager::class));
return new CloudIdManager(
$c->get(\OCP\Contacts\IManager::class),
$c->get(IURLGenerator::class),
$c->get(IUserManager::class),
$c->get(ICacheFactory::class),
$c->get(EventDispatcherInterface::class),
);
});

$this->registerAlias(\OCP\GlobalScale\IConfig::class, \OC\GlobalScale\Config::class);

Loading…
Cancel
Save