Skip to content
20 changes: 20 additions & 0 deletions lib/Controller/ChatController.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
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;
Expand Down Expand Up @@ -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;
Expand All @@ -97,6 +99,7 @@ public function __construct(string $appName,
AttachmentService $attachmentService,
GuestManager $guestManager,
MessageParser $messageParser,
RoomShareProvider $shareProvider,
IManager $autoCompleteManager,
IUserStatusManager $statusManager,
MatterbridgeManager $matterbridgeManager,
Expand All @@ -119,6 +122,7 @@ public function __construct(string $appName,
$this->attachmentService = $attachmentService;
$this->guestManager = $guestManager;
$this->messageParser = $messageParser;
$this->shareProvider = $shareProvider;
$this->autoCompleteManager = $autoCompleteManager;
$this->statusManager = $statusManager;
$this->matterbridgeManager = $matterbridgeManager;
Expand Down Expand Up @@ -432,6 +436,22 @@ public function receiveMessages(int $lookIntoFuture,
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) {
Expand Down
54 changes: 54 additions & 0 deletions lib/Share/RoomShareProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

namespace OCA\Talk\Share;

use OC\Cache\CappedMemoryCache;
use OC\Files\Cache\Cache;
use OCA\Talk\Events\AlreadySharedEvent;
use OCA\Talk\Events\RoomEvent;
Expand Down Expand Up @@ -83,6 +84,8 @@ class RoomShareProvider implements IShareProvider {
private IL10N $l;
private IMimeTypeLoader $mimeTypeLoader;

private $sharesByIdCache;

public function __construct(
IDBConnection $connection,
ISecureRandom $secureRandom,
Expand All @@ -103,6 +106,7 @@ public function __construct(
$this->timeFactory = $timeFactory;
$this->l = $l;
$this->mimeTypeLoader = $mimeTypeLoader;
$this->sharesByIdCache = new CappedMemoryCache();
}

public static function register(IEventDispatcher $dispatcher): void {
Expand Down Expand Up @@ -631,6 +635,11 @@ public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offs
* @throws ShareNotFound
*/
public function getShareById($id, $recipientId = null): IShare {

if (isset($this->sharesByIdCache[$id])) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cache needs to be invalidated on delete/update function calls

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have added cache invalidation (cleaning actually 😉) in all update/delete calls that seemed related in 03f6476.

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',
Expand Down Expand Up @@ -665,6 +674,51 @@ public function getShareById($id, $recipientId = null): IShare {
return $share;
}

/**
* 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.
*
Expand Down