Skip to content

Commit

Permalink
Cache the user backend info for 300s
Browse files Browse the repository at this point in the history
Signed-off-by: Joas Schilling <coding@schilljs.com>
  • Loading branch information
nickvergessen authored and backportbot[bot] committed Feb 17, 2021
1 parent 1db95da commit a745d58
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 39 deletions.
4 changes: 3 additions & 1 deletion apps/user_ldap/tests/LDAPProviderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
use OCA\User_LDAP\IGroupLDAP;
use OCA\User_LDAP\IUserLDAP;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\ICacheFactory;
use OCP\IConfig;
use OCP\IServerContainer;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
Expand Down Expand Up @@ -78,7 +79,8 @@ private function getUserManagerMock(IUserLDAP $userBackend) {
->setConstructorArgs([
$this->createMock(IConfig::class),
$this->createMock(EventDispatcherInterface::class),
$this->createMock(IEventDispatcher::class)
$this->createMock(ICacheFactory::class),
$this->createMock(IEventDispatcher::class),
])
->getMock();
$userManager->expects($this->any())
Expand Down
25 changes: 24 additions & 1 deletion lib/private/User/Manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
use OC\Hooks\PublicEmitter;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\ICache;
use OCP\ICacheFactory;
use OCP\IConfig;
use OCP\IGroup;
use OCP\IUser;
Expand Down Expand Up @@ -84,14 +86,19 @@ class Manager extends PublicEmitter implements IUserManager {
/** @var EventDispatcherInterface */
private $dispatcher;

/** @var ICache */
private $cache;

/** @var IEventDispatcher */
private $eventDispatcher;

public function __construct(IConfig $config,
EventDispatcherInterface $oldDispatcher,
ICacheFactory $cacheFactory,
IEventDispatcher $eventDispatcher) {
$this->config = $config;
$this->dispatcher = $oldDispatcher;
$this->cache = $cacheFactory->createDistributed('user_backend_map');
$cachedUsers = &$this->cachedUsers;
$this->listen('\OC\User', 'postDelete', function ($user) use (&$cachedUsers) {
/** @var \OC\User\User $user */
Expand Down Expand Up @@ -150,8 +157,24 @@ public function get($uid) {
if (isset($this->cachedUsers[$uid])) { //check the cache first to prevent having to loop over the backends
return $this->cachedUsers[$uid];
}
foreach ($this->backends as $backend) {

$cachedBackend = $this->cache->get($uid);
if ($cachedBackend !== null && isset($this->backends[$cachedBackend])) {
// Cache has the info of the user backend already, so ask that one directly
$backend = $this->backends[$cachedBackend];
if ($backend->userExists($uid)) {
return $this->getUserObject($uid, $backend);
}
}

foreach ($this->backends as $i => $backend) {
if ($i === $cachedBackend) {
// Tried that one already
continue;
}

if ($backend->userExists($uid)) {
$this->cache->set($uid, $i, 300);
return $this->getUserObject($uid, $backend);
}
}
Expand Down
3 changes: 2 additions & 1 deletion tests/lib/Files/Config/UserMountCacheTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use OC\User\Manager;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\Config\ICachedMountInfo;
use OCP\ICacheFactory;
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\IUserManager;
Expand Down Expand Up @@ -46,7 +47,7 @@ class UserMountCacheTest extends TestCase {
protected function setUp(): void {
$this->fileIds = [];
$this->connection = \OC::$server->getDatabaseConnection();
$this->userManager = new Manager($this->createMock(IConfig::class), $this->createMock(EventDispatcherInterface::class), $this->createMock(IEventDispatcher::class));
$this->userManager = new Manager($this->createMock(IConfig::class), $this->createMock(EventDispatcherInterface::class), $this->createMock(ICacheFactory::class), $this->createMock(IEventDispatcher::class));
$userBackend = new Dummy();
$userBackend->createUser('u1', '');
$userBackend->createUser('u2', '');
Expand Down
22 changes: 19 additions & 3 deletions tests/lib/Files/Storage/Wrapper/EncryptionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\Cache\ICache;
use OCP\Files\Mount\IMountPoint;
use OCP\ICacheFactory;
use OCP\IConfig;
use OCP\ILogger;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
Expand Down Expand Up @@ -131,7 +132,12 @@ protected function setUp(): void {

$this->util = $this->getMockBuilder('\OC\Encryption\Util')
->setMethods(['getUidAndFilename', 'isFile', 'isExcluded'])
->setConstructorArgs([new View(), new Manager($this->config, $this->createMock(EventDispatcherInterface::class), $this->createMock(IEventDispatcher::class)), $this->groupManager, $this->config, $this->arrayCache])
->setConstructorArgs([new View(), new Manager(
$this->config,
$this->createMock(EventDispatcherInterface::class),
$this->createMock(ICacheFactory::class),
$this->createMock(IEventDispatcher::class)
), $this->groupManager, $this->config, $this->arrayCache])
->getMock();
$this->util->expects($this->any())
->method('getUidAndFilename')
Expand Down Expand Up @@ -567,7 +573,12 @@ public function testGetHeader($path, $strippedPathExists, $strippedPath) {
->setConstructorArgs(
[
new View(),
new Manager($this->config, $this->createMock(EventDispatcherInterface::class), $this->createMock(IEventDispatcher::class)),
new Manager(
$this->config,
$this->createMock(EventDispatcherInterface::class),
$this->createMock(ICacheFactory::class),
$this->createMock(IEventDispatcher::class)
),
$this->groupManager,
$this->config,
$this->arrayCache
Expand Down Expand Up @@ -635,7 +646,12 @@ public function testGetHeaderAddLegacyModule($header, $isEncrypted, $exists, $ex
->willReturn($exists);

$util = $this->getMockBuilder('\OC\Encryption\Util')
->setConstructorArgs([new View(), new Manager($this->config, $this->createMock(EventDispatcherInterface::class), $this->createMock(IEventDispatcher::class)), $this->groupManager, $this->config, $this->arrayCache])
->setConstructorArgs([new View(), new Manager(
$this->config,
$this->createMock(EventDispatcherInterface::class),
$this->createMock(ICacheFactory::class),
$this->createMock(IEventDispatcher::class)
), $this->groupManager, $this->config, $this->arrayCache])
->getMock();

$cache = $this->getMockBuilder('\OC\Files\Cache\Cache')
Expand Down
8 changes: 7 additions & 1 deletion tests/lib/Files/Stream/EncryptionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use OC\Memcache\ArrayCache;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\Cache\ICache;
use OCP\ICacheFactory;
use OCP\IConfig;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;

Expand Down Expand Up @@ -49,7 +50,12 @@ protected function getStream($fileName, $mode, $unencryptedSize, $wrapper = '\OC
$file->expects($this->any())->method('getAccessList')->willReturn([]);
$util = $this->getMockBuilder('\OC\Encryption\Util')
->setMethods(['getUidAndFilename'])
->setConstructorArgs([new View(), new \OC\User\Manager($config, $this->createMock(EventDispatcherInterface::class), $this->createMock(IEventDispatcher::class)), $groupManager, $config, $arrayCache])
->setConstructorArgs([new View(), new \OC\User\Manager(
$config,
$this->createMock(EventDispatcherInterface::class),
$this->createMock(ICacheFactory::class),
$this->createMock(IEventDispatcher::class)
), $groupManager, $config, $arrayCache])
->getMock();
$util->expects($this->any())
->method('getUidAndFilename')
Expand Down
Loading

0 comments on commit a745d58

Please sign in to comment.