]> source.dussan.org Git - nextcloud-server.git/commitdiff
Implement reference provider based caching
authorJulius Härtl <jus@bitgrid.net>
Fri, 12 Aug 2022 16:22:52 +0000 (18:22 +0200)
committerJulius Härtl <jus@bitgrid.net>
Wed, 31 Aug 2022 14:20:06 +0000 (16:20 +0200)
Signed-off-by: Julius Härtl <jus@bitgrid.net>
lib/private/Collaboration/Reference/FileReferenceProvider.php
lib/private/Collaboration/Reference/LinkReferenceProvider.php
lib/private/Collaboration/Reference/ReferenceManager.php
lib/public/Collaboration/Reference/IReferenceProvider.php

index 9fb083f749c1748dbb7d5dde22a03704fdbd2da9..b7c9bc9cd561fe3e8ab547457d10020f0df91bbc 100644 (file)
@@ -41,8 +41,13 @@ class FileReferenceProvider implements IReferenceProvider {
                $this->userId = $userSession->getUser() ? $userSession->getUser()->getUID() : null;
        }
 
+       public function matchReference(string $referenceText): bool {
+               return str_starts_with($referenceText, $this->urlGenerator->getAbsoluteURL('/index.php/f/'))
+                       || str_starts_with($referenceText, $this->urlGenerator->getAbsoluteURL('/f/'));
+       }
+
        public function resolveReference(string $referenceText): ?IReference {
-               if (str_starts_with($referenceText, $this->urlGenerator->getAbsoluteURL('/index.php/f/')) || str_starts_with($referenceText, $this->urlGenerator->getAbsoluteURL('/f/'))) {
+               if ($this->matchReference($referenceText)) {
                        $reference = new Reference($referenceText);
                        try {
                                $this->fetchReference($reference);
@@ -62,6 +67,10 @@ class FileReferenceProvider implements IReferenceProvider {
         * @throws \OC\User\NoUserException
         */
        private function fetchReference(Reference $reference) {
+               if ($this->userId === null) {
+                       throw new NotFoundException();
+               }
+
                $fileId = str_replace($this->urlGenerator->getAbsoluteURL('/index.php/f/'), '', $reference->getId());
                $fileId = str_replace($this->urlGenerator->getAbsoluteURL('/f/'), '', $fileId);
 
@@ -90,4 +99,12 @@ class FileReferenceProvider implements IReferenceProvider {
                        'preview-available' => false
                ]);
        }
+
+       public function isGloballyCachable(): bool {
+               return false;
+       }
+
+       public function getCacheKey(string $referenceId): string {
+               return $this->userId;
+       }
 }
index b4c44344476587890a76c732fbfb79a1b2a2e746..0f3ff5f67329e16e3312de1cc7cfbc276b65d7d8 100644 (file)
@@ -44,12 +44,16 @@ class LinkReferenceProvider implements IReferenceProvider {
                $this->systemConfig = $systemConfig;
        }
 
-       public function resolveReference(string $referenceText): ?IReference {
+       public function matchReference(string $referenceText): bool {
                if ($this->systemConfig->getValue('reference_opengraph', true) !== true) {
-                       return null;
+                       return false;
                }
 
-               if (preg_match(self::URL_PATTERN, $referenceText)) {
+               return (bool)preg_match(self::URL_PATTERN, $referenceText);
+       }
+
+       public function resolveReference(string $referenceText): ?IReference {
+               if ($this->matchReference($referenceText)) {
                        $reference = new Reference($referenceText);
                        $this->fetchReference($reference);
                        return $reference;
@@ -87,4 +91,12 @@ class LinkReferenceProvider implements IReferenceProvider {
                        $reference->setImageUrl($object->images[0]->url);
                }
        }
+
+       public function isGloballyCachable(): bool {
+               return true;
+       }
+
+       public function getCacheKey(string $referenceId): string {
+               return '';
+       }
 }
index 6f0ef37198e29579b427c990124b5a907ffd6090..5cab10c0ef510e4a4be3fc5f6cb90284388704a7 100644 (file)
@@ -54,20 +54,31 @@ class ReferenceManager implements IReferenceManager {
        }
 
        public function resolveReference(string $referenceId): ?IReference {
-               $cached = $this->cache->get($referenceId);
+               $matchedProvider = null;
+               foreach ($this->providers as $provider) {
+                       $matchedProvider = $provider->matchReference($referenceId) ? $provider : null;
+               }
+
+               if ($matchedProvider === null) {
+                       $matchedProvider = $this->linkReferenceProvider;
+               }
+
+               $cacheKey = md5(serialize([
+                       $matchedProvider->isGloballyCachable() ? 0 : $matchedProvider->getCacheKey($referenceId),
+                       $referenceId
+               ]));
+               $cached = $this->cache->get($cacheKey);
                if ($cached) {
-                       // TODO: Figure out caching for references that depend on the viewer user
                        return Reference::fromCache($cached);
                }
-               foreach ($this->providers as $provider) {
-                       $reference = $provider->resolveReference($referenceId);
-                       if ($reference) {
-                               $this->cache->set($referenceId, Reference::toCache($reference), 60);
-                               return $reference;
-                       }
+
+               $reference = $matchedProvider->resolveReference($referenceId);
+               if ($reference) {
+                       $this->cache->set($cacheKey, Reference::toCache($reference), 60);
+                       return $reference;
                }
 
-               return $this->linkReferenceProvider->resolveReference($referenceId);
+               return null;
        }
 
        public function registerReferenceProvider(IReferenceProvider $provider): void {
index 232874709c2c7dc511fd414dcae6db7d57984812..ff0bfc8ed473ad9ae257bf0b677b17677035f461 100644 (file)
@@ -23,5 +23,8 @@
 namespace OCP\Collaboration\Reference;
 
 interface IReferenceProvider {
+       public function matchReference(string $referenceText): bool;
        public function resolveReference(string $referenceText): ?IReference;
+       public function isGloballyCachable(): bool;
+       public function getCacheKey(string $referenceId): string;
 }