From 8af96afbff2edee36019727bfeaa061ce45b0f79 Mon Sep 17 00:00:00 2001 From: Louis Chemineau Date: Thu, 20 Oct 2022 16:37:47 +0200 Subject: [PATCH] Listen to cache event for managing metadata Signed-off-by: Louis Chemineau --- core/Application.php | 9 +-- lib/private/Metadata/FileEventListener.php | 81 +++++++--------------- 2 files changed, 27 insertions(+), 63 deletions(-) diff --git a/core/Application.php b/core/Application.php index 749f2d176d440..41123fb3eeae4 100644 --- a/core/Application.php +++ b/core/Application.php @@ -52,9 +52,8 @@ use OC\TagManager; use OCP\AppFramework\App; use OCP\EventDispatcher\IEventDispatcher; -use OCP\Files\Events\Node\NodeDeletedEvent; -use OCP\Files\Events\Node\NodeWrittenEvent; -use OCP\Files\Events\NodeRemovedFromCache; +use OCP\Files\Cache\NodeWrittenEvent; +use OCP\Files\Cache\CacheEntryRemovedEvent; use OCP\IDBConnection; use OCP\User\Events\BeforeUserDeletedEvent; use OCP\User\Events\UserDeletedEvent; @@ -327,9 +326,7 @@ function (GenericEvent $event) use ($container) { $config = $container->get(IConfig::class); if ($config->getSystemValueBool('enable_file_metadata', true)) { /** @psalm-suppress InvalidArgument */ - $eventDispatcher->addServiceListener(NodeDeletedEvent::class, FileEventListener::class); - /** @psalm-suppress InvalidArgument */ - $eventDispatcher->addServiceListener(NodeRemovedFromCache::class, FileEventListener::class); + $eventDispatcher->addServiceListener(CacheEntryRemovedEvent::class, FileEventListener::class); /** @psalm-suppress InvalidArgument */ $eventDispatcher->addServiceListener(NodeWrittenEvent::class, FileEventListener::class); } diff --git a/lib/private/Metadata/FileEventListener.php b/lib/private/Metadata/FileEventListener.php index 162e85ff3aa9d..fe6e676cac522 100644 --- a/lib/private/Metadata/FileEventListener.php +++ b/lib/private/Metadata/FileEventListener.php @@ -21,89 +21,56 @@ namespace OC\Metadata; -use OC\Files\Filesystem; use OCP\EventDispatcher\Event; use OCP\EventDispatcher\IEventListener; -use OCP\Files\Events\Node\NodeDeletedEvent; +use OCP\Files\Cache\CacheEntryRemovedEvent; use OCP\Files\Events\Node\NodeWrittenEvent; -use OCP\Files\Events\NodeRemovedFromCache; use OCP\Files\File; -use OCP\Files\Node; -use OCP\Files\NotFoundException; -use OCP\Files\FileInfo; -use Psr\Log\LoggerInterface; /** - * @template-implements IEventListener - * @template-implements IEventListener - * @template-implements IEventListener + * @template-implements IEventListener + * @template-implements IEventListener */ class FileEventListener implements IEventListener { private IMetadataManager $manager; - private LoggerInterface $logger; - public function __construct(IMetadataManager $manager, LoggerInterface $logger) { + public function __construct( + IMetadataManager $manager + ) { $this->manager = $manager; - $this->logger = $logger; - } - - private function shouldExtractMetadata(Node $node): bool { - try { - if ($node->getMimetype() === 'httpd/unix-directory') { - return false; - } - } catch (NotFoundException $e) { - return false; - } - if ($node->getSize(false) <= 0) { - return false; - } - - $path = $node->getPath(); - return $this->isCorrectPath($path); } private function isCorrectPath(string $path): bool { // TODO make this more dynamic, we have the same issue in other places - return !str_starts_with($path, 'appdata_') && !str_starts_with($path, 'files_versions/') && !str_starts_with($path, 'files_trashbin/'); + return !str_starts_with($path, 'appdata_') && !str_starts_with($path, 'files_versions/'); } + /** + * @param NodeWrittenEvent|CacheEntryRemovedEvent $event + */ public function handle(Event $event): void { - if ($event instanceof NodeRemovedFromCache) { - if (!$this->isCorrectPath($event->getPath())) { - // Don't listen to paths for which we don't extract metadata - return; - } - $view = Filesystem::getView(); - if (!$view) { - // Should not happen since a scan in the user folder should setup - // the file system. - $e = new \Exception(); // don't trigger, just get backtrace - $this->logger->error('Detecting deletion of a file with possible metadata but file system setup is not setup', [ - 'exception' => $e, - 'app' => 'metadata' - ]); + if ($event instanceof CacheEntryRemovedEvent) { + if ($event->getStorage()->is_dir($event->getPath())) { return; } - $info = $view->getFileInfo($event->getPath()); - if ($info && $info->getType() === FileInfo::TYPE_FILE) { - $this->manager->clearMetadata($info->getId()); - } - } - if ($event instanceof NodeDeletedEvent) { - $node = $event->getNode(); - if ($this->shouldExtractMetadata($node)) { - /** @var File $node */ - $this->manager->clearMetadata($event->getNode()->getId()); + if ($this->isCorrectPath($event->getPath())) { + $this->manager->clearMetadata($event->getFileId()); } } if ($event instanceof NodeWrittenEvent) { $node = $event->getNode(); - if ($this->shouldExtractMetadata($node)) { - /** @var File $node */ - $this->manager->generateMetadata($event->getNode(), false); + if ($node->getSize(false) <= 0) { + return; + } + + if (!$this->isCorrectPath($node->getPath())) { + return; + } + + if ($node instanceof File) { + $this->manager->generateMetadata($node, false); } } }