зеркало из https://github.com/nextcloud/spreed.git
Left join the last comment instead of doing O(n) queries
Signed-off-by: Joas Schilling <coding@schilljs.com>
This commit is contained in:
Родитель
27cd7954ae
Коммит
f37e260ac5
|
@ -17,7 +17,7 @@ And in the works for the [coming versions](https://github.com/nextcloud/spreed/m
|
|||
|
||||
]]></description>
|
||||
|
||||
<version>3.99.5</version>
|
||||
<version>3.99.6</version>
|
||||
<licence>agpl</licence>
|
||||
|
||||
<author>Daniel Calviño Sánchez</author>
|
||||
|
|
|
@ -76,6 +76,9 @@ class ChatManager {
|
|||
|
||||
$this->commentsManager->save($comment);
|
||||
|
||||
// Update last_message
|
||||
$chat->setLastMessage($comment);
|
||||
|
||||
$this->notifier->notifyMentionedUsers($chat, $comment);
|
||||
return $comment;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,14 @@ use OCP\DB\QueryBuilder\IQueryBuilder;
|
|||
|
||||
class CommentsManager extends Manager {
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @return IComment
|
||||
*/
|
||||
public function getCommentFromData(array $data): IComment {
|
||||
return new Comment($this->normalizeDatabaseData($data));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $objectType
|
||||
* @param string $objectId
|
||||
|
|
|
@ -38,6 +38,7 @@ use OCA\Spreed\TalkSession;
|
|||
use OCP\AppFramework\Http;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\AppFramework\OCSController;
|
||||
use OCP\Comments\IComment;
|
||||
use OCP\IL10N;
|
||||
use OCP\ILogger;
|
||||
use OCP\IRequest;
|
||||
|
@ -115,7 +116,7 @@ class RoomController extends OCSController {
|
|||
* @return DataResponse
|
||||
*/
|
||||
public function getRooms() {
|
||||
$rooms = $this->manager->getRoomsForParticipant($this->userId);
|
||||
$rooms = $this->manager->getRoomsForParticipant($this->userId, true);
|
||||
|
||||
$return = [];
|
||||
foreach ($rooms as $room) {
|
||||
|
@ -249,35 +250,35 @@ class RoomController extends OCSController {
|
|||
$room->cleanGuestParticipants();
|
||||
}
|
||||
|
||||
$lastMessageFromHistory = $this->chatManager->getHistory($room->getId(), 0, 1);
|
||||
$lastMessage = [];
|
||||
$lastMessage = $room->getLastMessage();
|
||||
if ($lastMessage instanceof IComment) {
|
||||
|
||||
if (!empty($lastMessageFromHistory)) {
|
||||
|
||||
list($message, $messageParameters) = $this->richMessageHelper->getRichMessage($lastMessageFromHistory[0]);
|
||||
list($message, $messageParameters) = $this->richMessageHelper->getRichMessage($lastMessage);
|
||||
|
||||
$displayName = '';
|
||||
|
||||
$actorId = $lastMessageFromHistory[0]->getActorId();
|
||||
$actorType = $lastMessageFromHistory[0]->getActorType();
|
||||
$actorId = $lastMessage->getActorId();
|
||||
$actorType = $lastMessage->getActorType();
|
||||
|
||||
if ($actorType === 'users') {
|
||||
$user = $this->userManager->get($actorId);
|
||||
$displayName = $user instanceof IUser ? $user->getDisplayName() : '';
|
||||
} else if ($actorType === 'guests') {
|
||||
$guestNames = !empty($actorId) ? $this->guestManager->getNamesBySessionHashes([$actorId]) : [];
|
||||
$displayName = isset($guestNames[$actorId]) ? $guestNames[$actorId] : '';
|
||||
$displayName = $guestNames[$actorId] ?? '';
|
||||
}
|
||||
|
||||
$lastMessage = [
|
||||
'id' => $lastMessageFromHistory[0]->getId(),
|
||||
'id' => $lastMessage->getId(),
|
||||
'actorType' => $actorType,
|
||||
'actorId' => $actorId,
|
||||
'actorDisplayName' => $displayName,
|
||||
'timestamp' => $lastMessageFromHistory[0]->getCreationDateTime()->getTimestamp(),
|
||||
'timestamp' => $lastMessage->getCreationDateTime()->getTimestamp(),
|
||||
'message' => $message,
|
||||
'messageParameters' => $messageParameters,
|
||||
];
|
||||
} else {
|
||||
$lastMessage = [];
|
||||
}
|
||||
|
||||
$roomData = array_merge($roomData, [
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
namespace OCA\Spreed;
|
||||
|
||||
|
||||
use OCA\Spreed\Chat\CommentsManager;
|
||||
use OCA\Spreed\Exceptions\RoomNotFoundException;
|
||||
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||
use OCP\IConfig;
|
||||
|
@ -39,6 +40,8 @@ class Manager {
|
|||
private $config;
|
||||
/** @var ISecureRandom */
|
||||
private $secureRandom;
|
||||
/** @var CommentsManager */
|
||||
private $commentsManager;
|
||||
/** @var EventDispatcherInterface */
|
||||
private $dispatcher;
|
||||
/** @var IHasher */
|
||||
|
@ -50,13 +53,15 @@ class Manager {
|
|||
* @param IDBConnection $db
|
||||
* @param IConfig $config
|
||||
* @param ISecureRandom $secureRandom
|
||||
* @param CommentsManager $commentsManager
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
* @param IHasher $hasher
|
||||
*/
|
||||
public function __construct(IDBConnection $db, IConfig $config, ISecureRandom $secureRandom, EventDispatcherInterface $dispatcher, IHasher $hasher) {
|
||||
public function __construct(IDBConnection $db, IConfig $config, ISecureRandom $secureRandom, CommentsManager $commentsManager, EventDispatcherInterface $dispatcher, IHasher $hasher) {
|
||||
$this->db = $db;
|
||||
$this->config = $config;
|
||||
$this->secureRandom = $secureRandom;
|
||||
$this->commentsManager = $commentsManager;
|
||||
$this->dispatcher = $dispatcher;
|
||||
$this->hasher = $hasher;
|
||||
}
|
||||
|
@ -89,7 +94,12 @@ class Manager {
|
|||
$lastActivity = new \DateTime($row['last_activity']);
|
||||
}
|
||||
|
||||
return new Room($this, $this->db, $this->secureRandom, $this->dispatcher, $this->hasher, (int) $row['id'], (int) $row['type'], $row['token'], $row['name'], $row['password'], (int) $row['active_guests'], $activeSince, $lastActivity);
|
||||
$lastMessage = null;
|
||||
if (!empty($row['comment_id'])) {
|
||||
$lastMessage = $this->commentsManager->getCommentFromData(array_merge($row, ['id' => $row['comment_id']]));
|
||||
}
|
||||
|
||||
return new Room($this, $this->db, $this->secureRandom, $this->dispatcher, $this->hasher, (int) $row['id'], (int) $row['type'], $row['token'], $row['name'], $row['password'], (int) $row['active_guests'], $activeSince, $lastActivity, $lastMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -103,11 +113,12 @@ class Manager {
|
|||
|
||||
/**
|
||||
* @param string $participant
|
||||
* @param bool $includeLastMessage
|
||||
* @return Room[]
|
||||
*/
|
||||
public function getRoomsForParticipant($participant) {
|
||||
public function getRoomsForParticipant($participant, $includeLastMessage = false) {
|
||||
$query = $this->db->getQueryBuilder();
|
||||
$query->select('*')
|
||||
$query->select('r.*')->addSelect('p.*')
|
||||
->from('talk_rooms', 'r')
|
||||
->leftJoin('r', 'talk_participants', 'p', $query->expr()->andX(
|
||||
$query->expr()->eq('p.user_id', $query->createNamedParameter($participant)),
|
||||
|
@ -115,6 +126,12 @@ class Manager {
|
|||
))
|
||||
->where($query->expr()->isNotNull('p.user_id'));
|
||||
|
||||
if ($includeLastMessage) {
|
||||
$query->leftJoin('r','comments', 'c', $query->expr()->eq('r.last_message', 'c.id'));
|
||||
$query->selectAlias('c.id', 'comment_id');
|
||||
$query->addSelect('c.actor_id', 'c.actor_type', 'c.message', 'c.creation_timestamp');
|
||||
}
|
||||
|
||||
$result = $query->execute();
|
||||
$rooms = [];
|
||||
while ($row = $result->fetch()) {
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2018, Joas Schilling <coding@schilljs.com>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
namespace OCA\Spreed\Migration;
|
||||
|
||||
use Doctrine\DBAL\Types\Type;
|
||||
use OCP\DB\ISchemaWrapper;
|
||||
use OCP\IDBConnection;
|
||||
use OCP\Migration\SimpleMigrationStep;
|
||||
use OCP\Migration\IOutput;
|
||||
|
||||
class Version3003Date20180718133519 extends SimpleMigrationStep {
|
||||
|
||||
/** @var IDBConnection */
|
||||
protected $connection;
|
||||
|
||||
public function __construct(IDBConnection $connection) {
|
||||
$this->connection = $connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IOutput $output
|
||||
* @param \Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
|
||||
* @param array $options
|
||||
* @return null|ISchemaWrapper
|
||||
* @since 13.0.0
|
||||
*/
|
||||
public function changeSchema(IOutput $output, \Closure $schemaClosure, array $options) {
|
||||
/** @var ISchemaWrapper $schema */
|
||||
$schema = $schemaClosure();
|
||||
|
||||
$table = $schema->getTable('talk_rooms');
|
||||
|
||||
if (!$table->hasColumn('last_message')) {
|
||||
$table->addColumn('last_message', Type::BIGINT, [
|
||||
'notnull' => false,
|
||||
'default' => 0,
|
||||
]);
|
||||
}
|
||||
|
||||
return $schema;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IOutput $output
|
||||
* @param \Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
|
||||
* @param array $options
|
||||
* @since 13.0.0
|
||||
*/
|
||||
public function postSchemaChange(IOutput $output, \Closure $schemaClosure, array $options) {
|
||||
$update = $this->connection->getQueryBuilder();
|
||||
$update->update('talk_rooms')
|
||||
->set('last_message', $update->createParameter('message'))
|
||||
->where($update->expr()->eq('id', $update->createParameter('room')));
|
||||
|
||||
$query = $this->connection->getQueryBuilder();
|
||||
$query->selectAlias($query->createFunction('MAX(' . $query->getColumnName('id') . ')'), 'message')
|
||||
->addSelect('object_id')
|
||||
->from('comments')
|
||||
->where($query->expr()->eq('object_type', $query->createNamedParameter('chat')))
|
||||
->groupBy('object_id');
|
||||
|
||||
$result = $query->execute();
|
||||
while ($row = $result->fetch()) {
|
||||
$update->setParameter('message', $row['message'])
|
||||
->setParameter('room', $row['object_id']);
|
||||
$update->execute();
|
||||
}
|
||||
$result->closeCursor();
|
||||
}
|
||||
}
|
22
lib/Room.php
22
lib/Room.php
|
@ -27,6 +27,7 @@ namespace OCA\Spreed;
|
|||
|
||||
use OCA\Spreed\Exceptions\InvalidPasswordException;
|
||||
use OCA\Spreed\Exceptions\ParticipantNotFoundException;
|
||||
use OCP\Comments\IComment;
|
||||
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||
use OCP\IDBConnection;
|
||||
use OCP\IUser;
|
||||
|
@ -68,6 +69,8 @@ class Room {
|
|||
private $activeSince;
|
||||
/** @var \DateTime|null */
|
||||
private $lastActivity;
|
||||
/** @var IComment|null */
|
||||
private $lastMessage;
|
||||
|
||||
/** @var string */
|
||||
protected $currentUser;
|
||||
|
@ -90,8 +93,9 @@ class Room {
|
|||
* @param int $activeGuests
|
||||
* @param \DateTime|null $activeSince
|
||||
* @param \DateTime|null $lastActivity
|
||||
* @param IComment|null $lastMessage
|
||||
*/
|
||||
public function __construct(Manager $manager, IDBConnection $db, ISecureRandom $secureRandom, EventDispatcherInterface $dispatcher, IHasher $hasher, $id, $type, $token, $name, $password, $activeGuests, \DateTime $activeSince = null, \DateTime $lastActivity = null) {
|
||||
public function __construct(Manager $manager, IDBConnection $db, ISecureRandom $secureRandom, EventDispatcherInterface $dispatcher, IHasher $hasher, $id, $type, $token, $name, $password, $activeGuests, \DateTime $activeSince = null, \DateTime $lastActivity = null, IComment $lastMessage = null) {
|
||||
$this->manager = $manager;
|
||||
$this->db = $db;
|
||||
$this->secureRandom = $secureRandom;
|
||||
|
@ -105,6 +109,7 @@ class Room {
|
|||
$this->activeGuests = $activeGuests;
|
||||
$this->activeSince = $activeSince;
|
||||
$this->lastActivity = $lastActivity;
|
||||
$this->lastMessage = $lastMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -156,6 +161,13 @@ class Room {
|
|||
return $this->lastActivity;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return IComment|null
|
||||
*/
|
||||
public function getLastMessage() {
|
||||
return $this->lastMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
|
@ -369,6 +381,14 @@ class Room {
|
|||
return true;
|
||||
}
|
||||
|
||||
public function setLastMessage(IComment $message) {
|
||||
$query = $this->db->getQueryBuilder();
|
||||
$query->update('talk_rooms')
|
||||
->set('last_message', $query->createNamedParameter((int) $message->getId()))
|
||||
->where($query->expr()->eq('id', $query->createNamedParameter($this->getId(), IQueryBuilder::PARAM_INT)));
|
||||
$query->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
|
|
Загрузка…
Ссылка в новой задаче