summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDariusz Olszewski <starypatyk@users.noreply.github.com>2022-08-13 23:47:48 +0200
committerJoas Schilling <coding@schilljs.com>2022-08-17 13:31:22 +0200
commitce2fa3a2392f05643d97cb8b1d717d42e9264dc9 (patch)
tree7c1df3c51782390c4b839f3c004c43e70bf59888
parent5871010f430c9775b1a20ad0feb249f3f2675301 (diff)
Reduce number of queries required to read shares
Signed-off-by: Dariusz Olszewski <starypatyk@users.noreply.github.com>
-rw-r--r--lib/Controller/ChatController.php20
-rw-r--r--lib/Share/RoomShareProvider.php54
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 b34209d99..0c751452b 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