Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FIX] Too many request on loadHistory method #21594

Merged
merged 10 commits into from
Apr 26, 2021
34 changes: 27 additions & 7 deletions app/lib/server/functions/loadMessageHistory.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ settings.get('Hide_System_Messages', function(key, values) {
hiddenTypes.forEach((item) => hideMessagesOfTypeServer.add(item));
});

export const loadMessageHistory = function loadMessageHistory({ userId, rid, end, limit = 20, ls }) {
export const loadMessageHistory = function loadMessageHistory({ userId, rid, end, limit = 20, ls, showThreadMessages = true }) {
const room = Rooms.findOne(rid, { fields: { sysMes: 1 } });

const hiddenMessageTypes = Array.isArray(room && room.sysMes) ? room.sysMes : Array.from(hideMessagesOfTypeServer.values()); // TODO probably remove on chained event system
Expand All @@ -27,7 +27,20 @@ export const loadMessageHistory = function loadMessageHistory({ userId, rid, end
};
}

const records = end != null ? Messages.findVisibleByRoomIdBeforeTimestampNotContainingTypes(rid, end, hiddenMessageTypes, options).fetch() : Messages.findVisibleByRoomIdNotContainingTypes(rid, hiddenMessageTypes, options).fetch();
const records = end != null
? Messages.findVisibleByRoomIdBeforeTimestampNotContainingTypes(
rid,
end,
hiddenMessageTypes,
options,
showThreadMessages,
).fetch()
: Messages.findVisibleByRoomIdNotContainingTypes(
rid,
hiddenMessageTypes,
options,
showThreadMessages,
).fetch();
const messages = normalizeMessagesForUser(records, userId);
let unreadNotLoaded = 0;
let firstUnread;
Expand All @@ -37,12 +50,19 @@ export const loadMessageHistory = function loadMessageHistory({ userId, rid, end

if ((firstMessage != null ? firstMessage.ts : undefined) > ls) {
delete options.limit;
const unreadMessages = Messages.findVisibleByRoomIdBetweenTimestampsNotContainingTypes(rid, ls, firstMessage.ts, hiddenMessageTypes, {
limit: 1,
sort: {
ts: 1,
const unreadMessages = Messages.findVisibleByRoomIdBetweenTimestampsNotContainingTypes(
rid,
ls,
firstMessage.ts,
hiddenMessageTypes,
{
limit: 1,
sort: {
ts: 1,
},
},
});
showThreadMessages,
);

firstUnread = unreadMessages.fetch()[0];
unreadNotLoaded = unreadMessages.count();
Expand Down
27 changes: 24 additions & 3 deletions app/models/server/models/Messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -251,12 +251,19 @@ export class Messages extends Base {
return this.find(query, options);
}

findVisibleByRoomIdNotContainingTypes(roomId, types, options) {
findVisibleByRoomIdNotContainingTypes(roomId, types, options, showThreadMessages = true) {
const query = {
_hidden: {
$ne: true,
},
rid: roomId,
...!showThreadMessages && {
$or: [{
tmid: { $exists: false },
}, {
tshow: true,
}],
},
};

if (Match.test(types, [String]) && (types.length > 0)) {
Expand Down Expand Up @@ -360,7 +367,7 @@ export class Messages extends Base {
return this.find(query, options);
}

findVisibleByRoomIdBeforeTimestampNotContainingTypes(roomId, timestamp, types, options) {
findVisibleByRoomIdBeforeTimestampNotContainingTypes(roomId, timestamp, types, options, showThreadMessages = true) {
const query = {
_hidden: {
$ne: true,
Expand All @@ -369,6 +376,13 @@ export class Messages extends Base {
ts: {
$lt: timestamp,
},
...!showThreadMessages && {
$or: [{
tmid: { $exists: false },
}, {
tshow: true,
}],
},
};

if (Match.test(types, [String]) && (types.length > 0)) {
Expand All @@ -378,7 +392,7 @@ export class Messages extends Base {
return this.find(query, options);
}

findVisibleByRoomIdBetweenTimestampsNotContainingTypes(roomId, afterTimestamp, beforeTimestamp, types, options) {
findVisibleByRoomIdBetweenTimestampsNotContainingTypes(roomId, afterTimestamp, beforeTimestamp, types, options, showThreadMessages = true) {
const query = {
_hidden: {
$ne: true,
Expand All @@ -388,6 +402,13 @@ export class Messages extends Base {
$gt: afterTimestamp,
$lt: beforeTimestamp,
},
...!showThreadMessages && {
$or: [{
tmid: { $exists: false },
}, {
tshow: true,
}],
},
};

if (Match.test(types, [String]) && (types.length > 0)) {
Expand Down
76 changes: 59 additions & 17 deletions app/ui-utils/client/lib/RoomHistoryManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import { Meteor } from 'meteor/meteor';
import { Tracker } from 'meteor/tracker';
import { ReactiveVar } from 'meteor/reactive-var';
import { Blaze } from 'meteor/blaze';
import { v4 as uuidv4 } from 'uuid';
import differenceInMilliseconds from 'date-fns/differenceInMilliseconds';
import { Emitter } from '@rocket.chat/emitter';

import { promises } from '../../../promises/client';
import { RoomManager } from './RoomManager';
Expand Down Expand Up @@ -99,9 +102,11 @@ const defaultLimit = parseInt(getConfig('roomListLimit')) || 50;

const waitAfterFlush = (fn) => setTimeout(() => Tracker.afterFlush(fn), 10);

export const RoomHistoryManager = new class {
export const RoomHistoryManager = new class extends Emitter {
constructor() {
super();
this.histories = {};
this.requestsList = [];
}

getRoom(rid) {
Expand All @@ -119,6 +124,37 @@ export const RoomHistoryManager = new class {
return this.histories[rid];
}

async queue() {
return new Promise((resolve) => {
const requestId = uuidv4();
const done = () => {
this.lastRequest = new Date();
resolve();
};
if (this.requestsList.length === 0) {
return this.run(done);
}
this.requestsList.push(requestId);
this.once(requestId, done);
});
}

run(fn) {
const difference = differenceInMilliseconds(new Date(), this.lastRequest);
if (!this.lastRequest || difference > 400) {
return fn();
}
return setTimeout(fn, 400 - difference);
ggazzo marked this conversation as resolved.
Show resolved Hide resolved
}

unqueue() {
const requestId = this.requestsList.pop();
if (!requestId) {
return;
}
this.run(() => this.emit(requestId));
}

async getMore(rid, limit = defaultLimit) {
let ts;
const room = this.getRoom(rid);
Expand All @@ -129,6 +165,8 @@ export const RoomHistoryManager = new class {

room.isLoading.set(true);

await this.queue();

// ScrollListener.setLoader true
const lastMessage = ChatMessage.findOne({ rid, _hidden: { $ne: true } }, { sort: { ts: 1 } });
// lastMessage ?= ChatMessage.findOne({rid: rid}, {sort: {ts: 1}})
Expand All @@ -151,8 +189,10 @@ export const RoomHistoryManager = new class {
typeName = (curRoomDoc ? curRoomDoc.t : undefined) + (curRoomDoc ? curRoomDoc.name : undefined);
}

// const showMessageInMainThread = getUserPreference(Meteor.userId(), 'showMessageInMainThread', false);
Copy link
Member

Choose a reason for hiding this comment

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

will this still be used?

Copy link
Member

Choose a reason for hiding this comment

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

I will, just commented to let you fetch all messages instead.

ggazzo marked this conversation as resolved.
Show resolved Hide resolved
const result = await call('loadHistory', rid, ts, limit, ls);
ggazzo marked this conversation as resolved.
Show resolved Hide resolved

this.unqueue();

let previousHeight;
let scroll;
Expand Down Expand Up @@ -182,6 +222,7 @@ export const RoomHistoryManager = new class {

room.loaded += visibleMessages.length;


if (messages.length < limit) {
room.hasMore.set(false);
}
Expand All @@ -202,12 +243,13 @@ export const RoomHistoryManager = new class {
});
}

getMoreNext(rid, limit = defaultLimit) {
async getMoreNext(rid, limit = defaultLimit) {
const room = this.getRoom(rid);
if (room.hasMoreNext.curValue !== true) {
return;
}

await this.queue();
const instance = Blaze.getView($('.messages-box .wrapper')[0]).templateInstance();
instance.atBottom = false;

Expand All @@ -229,25 +271,25 @@ export const RoomHistoryManager = new class {
const { ts } = lastMessage;

if (ts) {
return Meteor.call('loadNextMessages', rid, ts, limit, function(err, result) {
upsertMessageBulk({
msgs: Array.from(result.messages).filter((msg) => msg.t !== 'command'),
subscription,
});
const result = await call('loadNextMessages', rid, ts, limit);
upsertMessageBulk({
msgs: Array.from(result.messages).filter((msg) => msg.t !== 'command'),
subscription,
});

Meteor.defer(() => RoomManager.updateMentionsMarksOfRoom(typeName));
Meteor.defer(() => RoomManager.updateMentionsMarksOfRoom(typeName));

room.isLoading.set(false);
if (!room.loaded) {
room.loaded = 0;
}
room.isLoading.set(false);
if (!room.loaded) {
room.loaded = 0;
}

room.loaded += result.messages.length;
if (result.messages.length < limit) {
room.hasMoreNext.set(false);
}
});
room.loaded += result.messages.length;
if (result.messages.length < limit) {
room.hasMoreNext.set(false);
}
}
await this.unqueue();
}

async getSurroundingMessages(message, limit = defaultLimit) {
Expand Down
2 changes: 2 additions & 0 deletions client/lib/RoomManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ export class RoomStore extends Emitter<{

scroll?: number;

lm?: Date;

atBottom = true;

constructor(readonly rid: string) {
Expand Down
6 changes: 3 additions & 3 deletions server/methods/loadHistory.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import { check } from 'meteor/check';
import { Subscriptions } from '../../app/models';
import { hasPermission } from '../../app/authorization';
import { settings } from '../../app/settings';
import { loadMessageHistory } from '../../app/lib';
import { loadMessageHistory } from '../../app/lib/server';

Meteor.methods({
loadHistory(rid, end, limit = 20, ls) {
loadHistory(rid, end, limit = 20, ls, showThreadMessages = true) {
check(rid, String);

if (!Meteor.userId() && settings.get('Accounts_AllowAnonymousRead') === false) {
Expand All @@ -30,6 +30,6 @@ Meteor.methods({
return false;
}

return loadMessageHistory({ userId: fromId, rid, end, limit, ls });
return loadMessageHistory({ userId: fromId, rid, end, limit, ls, showThreadMessages });
},
});