diff options
author | Dariusz Olszewski <starypatyk@users.noreply.github.com> | 2022-08-14 00:47:48 +0300 |
---|---|---|
committer | Dariusz Olszewski <starypatyk@users.noreply.github.com> | 2022-08-14 00:48:44 +0300 |
commit | 254e7965f2878e4e83ddde6aa0a97de48f051620 (patch) | |
tree | 3a7c592ece2f5d1f8bf44ac1a2813c726c8408e5 /lib | |
parent | 064caa83862a88514b5c2b2e2100a6d999e2d198 (diff) |
Reduce number of queries required to read shares
Signed-off-by: Dariusz Olszewski <starypatyk@users.noreply.github.com>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Controller/ChatController.php | 20 | ||||
-rw-r--r-- | lib/Share/RoomShareProvider.php | 54 |
2 files changed, 74 insertions, 0 deletions
diff --git a/lib/Controller/ChatController.php b/lib/Controller/ChatController.php index ea7564439..1635e6852 100644 --- a/lib/Controller/ChatController.php +++ b/lib/Controller/ChatController.php @@ -40,6 +40,7 @@ use OCA\Talk\Room; use OCA\Talk\Service\AttachmentService; use OCA\Talk\Service\ParticipantService; use OCA\Talk\Service\SessionService; +use OCA\Talk\Share\RoomShareProvider; use OCP\App\IAppManager; use OCP\AppFramework\Http; use OCP\AppFramework\Http\DataResponse; @@ -74,6 +75,7 @@ class ChatController extends AEnvironmentAwareController { /** @var string[] */ protected array $guestNames; private MessageParser $messageParser; + protected RoomShareProvider $shareProvider; private IManager $autoCompleteManager; private IUserStatusManager $statusManager; protected MatterbridgeManager $matterbridgeManager; @@ -97,6 +99,7 @@ class ChatController extends AEnvironmentAwareController { AttachmentService $attachmentService, GuestManager $guestManager, MessageParser $messageParser, + RoomShareProvider $shareProvider, IManager $autoCompleteManager, IUserStatusManager $statusManager, MatterbridgeManager $matterbridgeManager, @@ -119,6 +122,7 @@ class ChatController extends AEnvironmentAwareController { $this->attachmentService = $attachmentService; $this->guestManager = $guestManager; $this->messageParser = $messageParser; + $this->shareProvider = $shareProvider; $this->autoCompleteManager = $autoCompleteManager; $this->statusManager = $statusManager; $this->matterbridgeManager = $matterbridgeManager; @@ -432,6 +436,22 @@ class ChatController extends AEnvironmentAwareController { return $response; } + // Quickly scan messages for share IDs + $share_ids = []; + foreach ($comments as $comment) { + $verb = $comment->getVerb(); + $message = $comment->getMessage(); + if ($verb === 'object_shared') { + $data = json_decode($message, true); + $parameters = $data['parameters']; + $share_ids[] = $parameters['share']; + } + } + // Ignore the result for now. Retrieved Share objects will be cached by + // the RoomShareProvider and returned from the cache to + // the MessageParser without additional database queries. + $this->shareProvider->getSharesByIds($share_ids); + $i = 0; $messages = $commentIdToIndex = $parentIds = []; foreach ($comments as $comment) { diff --git a/lib/Share/RoomShareProvider.php b/lib/Share/RoomShareProvider.php index 0494fc00c..229a23267 100644 --- a/lib/Share/RoomShareProvider.php +++ b/lib/Share/RoomShareProvider.php @@ -28,6 +28,7 @@ declare(strict_types=1); namespace OCA\Talk\Share; +use OC\Cache\CappedMemoryCache; use OC\Files\Cache\Cache; use OCA\Talk\Events\AlreadySharedEvent; use OCA\Talk\Events\RoomEvent; @@ -83,6 +84,8 @@ class RoomShareProvider implements IShareProvider { private IL10N $l; private IMimeTypeLoader $mimeTypeLoader; + private $sharesByIdCache; + public function __construct( IDBConnection $connection, ISecureRandom $secureRandom, @@ -103,6 +106,7 @@ class RoomShareProvider implements IShareProvider { $this->timeFactory = $timeFactory; $this->l = $l; $this->mimeTypeLoader = $mimeTypeLoader; + $this->sharesByIdCache = new CappedMemoryCache(); } public static function register(IEventDispatcher $dispatcher): void { @@ -631,6 +635,11 @@ class RoomShareProvider implements IShareProvider { * @throws ShareNotFound */ public function getShareById($id, $recipientId = null): IShare { + + if (isset($this->sharesByIdCache[$id])) { + return $this->sharesByIdCache[$id]; + } + $qb = $this->dbConnection->getQueryBuilder(); $qb->select('s.*', 'f.fileid', 'f.path', 'f.permissions AS f_permissions', 'f.storage', 'f.path_hash', @@ -666,6 +675,51 @@ class RoomShareProvider implements IShareProvider { } /** + * Get shares by ids + * + * Not part of IShareProvider API, but needed by OCA\Talk\Controller\ChatController. + * + * @param int[] $id + * @param string|null $recipientId + * @return IShare[] + * @throws ShareNotFound + */ + public function getSharesByIds($ids, $recipientId = null): array { + + $qb = $this->dbConnection->getQueryBuilder(); + $qb->select('s.*', + 'f.fileid', 'f.path', 'f.permissions AS f_permissions', 'f.storage', 'f.path_hash', + 'f.parent AS f_parent', 'f.name', 'f.mimetype', 'f.mimepart', 'f.size', 'f.mtime', 'f.storage_mtime', + 'f.encrypted', 'f.unencrypted_size', 'f.etag', 'f.checksum' + ) + ->selectAlias('st.id', 'storage_string_id') + ->from('share', 's') + ->leftJoin('s', 'filecache', 'f', $qb->expr()->eq('s.file_source', 'f.fileid')) + ->leftJoin('f', 'storages', 'st', $qb->expr()->eq('f.storage', 'st.numeric_id')) + ->where($qb->expr()->in('s.id', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY))) + ->andWhere($qb->expr()->eq('s.share_type', $qb->createNamedParameter(IShare::TYPE_ROOM))); + + $cursor = $qb->executeQuery(); + + $shares = []; + while ($data = $cursor->fetch()) { + $share = $this->createShareObject($data); + $id = (int) $share->getId(); + if (!isset($this->sharesByIdCache[$id])) { + $this->sharesByIdCache[$id] = $share; + } + $shares[] = $share; + } + $cursor->closeCursor(); + + if ($recipientId !== null) { + return $this->resolveSharesForRecipient($shares, $recipientId); + } else { + return $shares; + } + } + + /** * Returns each given share as seen by the given recipient. * * If the recipient has not modified the share the original one is returned |