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

[BREAK] Remove cache layer and internal calculated property room.usernames #10749

Merged
merged 62 commits into from
Jul 11, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
112ba74
Start removing cache
rodrigok Apr 29, 2018
c85929e
Merge remote-tracking branch 'origin/develop' into no-cache
rodrigok May 7, 2018
72d6068
Merge branch 'develop' into no-cache
rodrigok May 12, 2018
d272bbe
Use correct events for subscriptions and rooms
rodrigok May 12, 2018
2fe43a3
Remove getDynamicView
rodrigok May 12, 2018
f53e6f3
Remove _BaseCache
rodrigok May 12, 2018
346dde6
Remove `_room`
rodrigok May 12, 2018
76a03b2
Merge remote-tracking branch 'origin/develop' into no-cache
rodrigok May 16, 2018
3d7c2ba
Merge remote-tracking branch 'origin/develop' into no-cache
rodrigok May 30, 2018
a2ced5a
Fix merge from develop
rodrigok May 30, 2018
ac20bc2
Fix subscription event change
rodrigok May 30, 2018
9f18b37
Add more TODOs
rodrigok May 30, 2018
945d72a
Add migration and implement room.usersCount
rodrigok May 30, 2018
81b6e73
Use usersCount where we were using usernames.length
rodrigok May 30, 2018
ec4d38d
Identify TODOs
rodrigok May 31, 2018
4373e1f
Remove all on('changed'
rodrigok May 31, 2018
9ef79b7
Resolve fname and add tests
rodrigok May 31, 2018
b6e37b6
Improve migration of fname
rodrigok May 31, 2018
e4b95eb
Fix tests when running without oplog
rodrigok Jun 1, 2018
4114655
Reduce the internal oplog event complexity
rodrigok Jun 1, 2018
a0e8d69
Renamce `usernames` to `members` for apps
rodrigok Jun 1, 2018
9cf86f3
Resolve final itens from cache removal
rodrigok Jun 1, 2018
8ca44f5
Merge branch 'develop' into no-cache
engelgabriel Jun 4, 2018
1054af7
Merge remote-tracking branch 'origin/develop' into no-cache
rodrigok Jun 4, 2018
29d7eae
Merge remote-tracking branch 'origin/develop' into no-cache
rodrigok Jun 9, 2018
52e5fa7
Merge remote-tracking branch 'origin/develop' into no-cache
rodrigok Jun 9, 2018
2fe86d4
Do not get all settings from database and filter on server
rodrigok Jun 10, 2018
0ad9ba4
Merge remote-tracking branch 'origin/develop' into no-cache
rodrigok Jun 10, 2018
bff205e
Reduce the amount of calls for unlogged users
rodrigok Jun 10, 2018
83f22e9
Fix setting reactivity
rodrigok Jun 10, 2018
486d6e6
Add trace options for methods and subscriptions
rodrigok Jun 10, 2018
955cb24
Fix wrong name of setting `idleTimeoutLimit`
rodrigok Jun 10, 2018
d74f894
Merge remote-tracking branch 'origin/develop' into no-cache
ggazzo Jun 10, 2018
f656845
Fix slash command to invite users
rodrigok Jun 11, 2018
f0c0993
Merge branch 'develop' into no-cache
sampaiodiego Jun 11, 2018
9b48b27
Merge remote-tracking branch 'origin/develop' into no-cache
rodrigok Jun 11, 2018
ba9409e
Log has_connection and has_user to methor method calls
rodrigok Jun 11, 2018
4f126f6
Merge branch 'develop' into no-cache
sampaiodiego Jun 11, 2018
3573163
Merge remote-tracking branch 'origin/develop' into no-cache
rodrigok Jun 11, 2018
22b95f1
Merge branch 'no-cache' of https://github.com/RocketChat/Rocket.Chat …
rodrigok Jun 11, 2018
fd59135
Merge branch 'develop' into no-cache
rodrigok Jun 12, 2018
10fd2d8
Merge branch 'develop' into no-cache
sampaiodiego Jun 12, 2018
5dbf4bb
Merge branch 'develop' into no-cache
sampaiodiego Jun 12, 2018
cfde534
Merge branch 'develop' into no-cache
ggazzo Jun 12, 2018
187dbc5
Fix channels.members returning records without usernames
sampaiodiego Jun 14, 2018
5688daf
Merge remote-tracking branch 'origin/develop' into no-cache
rodrigok Jun 26, 2018
3258d55
Keep property `Room.usernames` as helper getter with deprecation warning
rodrigok Jun 26, 2018
96b28a8
Merge remote-tracking branch 'origin/develop' into no-cache
rodrigok Jun 29, 2018
d3c4fc6
Remove usage of usernames from slashcommand hide
rodrigok Jun 29, 2018
8fad0cd
Fix wrong variable name
rodrigok Jul 2, 2018
ec39105
review fix, and void filters on server using mongo db
ggazzo Jul 2, 2018
957e103
Merge branch 'no-cache' of github.com:RocketChat/Rocket.Chat into no-…
ggazzo Jul 2, 2018
c9403b4
removed duplicated rote
ggazzo Jul 2, 2018
19cbd46
Fix conflict
sampaiodiego Jul 2, 2018
d86c724
removed dumb spread
ggazzo Jul 2, 2018
3ceecc4
Merge branch 'no-cache' of github.com:RocketChat/Rocket.Chat into no-…
ggazzo Jul 2, 2018
1aad057
using model functions instead a generic
ggazzo Jul 2, 2018
381b99b
Merge remote-tracking branch 'origin/develop' into no-cache
rodrigok Jul 5, 2018
39e9daa
Remove the room transform that was faking the usernames property
rodrigok Jul 5, 2018
544c5e5
Fix strange behavior at users.setPreferences REST API
rodrigok Jul 6, 2018
6de47bc
Remove missing meta and $loki fields
rodrigok Jul 6, 2018
f27ac57
Merge remote-tracking branch 'origin/develop' into no-cache
rodrigok Jul 6, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions packages/rocketchat-action-links/both/lib/actionLinks.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ RocketChat.actionLinks = {
RocketChat.actionLinks.actions[name] = funct;
},
getMessage(name, messageId) {
if (!Meteor.userId()) {
const userId = Meteor.userId();
if (!userId) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', { function: 'actionLinks.getMessage' });
}

Expand All @@ -14,8 +15,11 @@ RocketChat.actionLinks = {
throw new Meteor.Error('error-invalid-message', 'Invalid message', { function: 'actionLinks.getMessage' });
}

const room = RocketChat.models.Rooms.findOne({ _id: message.rid });
if (Array.isArray(room.usernames) && room.usernames.indexOf(Meteor.user().username) === -1) {
const subscription = RocketChat.models.Subscriptions.findOne({
rid: message.rid,
'u._id': userId
});
if (!subscription) {
throw new Meteor.Error('error-not-allowed', 'Not allowed', { function: 'actionLinks.getMessage' });
}

Expand Down
8 changes: 3 additions & 5 deletions packages/rocketchat-api/server/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,7 @@ class API extends Restivus {
this.fieldSeparator = '.';
this.defaultFieldsToExclude = {
joinCode: 0,
$loki: 0,
meta: 0,
members: 0,
usernames: 0, // Please use the `channel/dm/group.members` endpoint. This is disabled for performance reasons
importIds: 0
};
this.limitedUserFieldsToExclude = {
Expand Down Expand Up @@ -85,13 +82,14 @@ class API extends Restivus {
return result;
}

failure(result, errorType) {
failure(result, errorType, stack) {
if (_.isObject(result)) {
result.success = false;
} else {
result = {
success: false,
error: result
error: result,
stack
};

if (errorType) {
Expand Down
142 changes: 84 additions & 58 deletions packages/rocketchat-api/server/v1/channels.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
import _ from 'underscore';

//Returns the channel IF found otherwise it will return the failure of why it didn't. Check the `statusCode` property
function findChannelByIdOrName({ params, checkedArchived = true, returnUsernames = false }) {
function findChannelByIdOrName({ params, checkedArchived = true }) {
if ((!params.roomId || !params.roomId.trim()) && (!params.roomName || !params.roomName.trim())) {
throw new Meteor.Error('error-roomid-param-not-provided', 'The parameter "roomId" or "roomName" is required');
}

const fields = { ...RocketChat.API.v1.defaultFieldsToExclude };
if (returnUsernames) {
delete fields.usernames;
}

let room;
if (params.roomId) {
Expand Down Expand Up @@ -143,7 +140,7 @@ RocketChat.API.v1.addRoute('channels.close', { authRequired: true }, {
RocketChat.API.v1.addRoute('channels.counters', { authRequired: true }, {
get() {
const access = RocketChat.authz.hasPermission(this.userId, 'view-room-administration');
const ruserId = this.requestParams().userId;
const userId = this.requestParams().userId;
let user = this.userId;
let unreads = null;
let userMentions = null;
Expand All @@ -152,34 +149,33 @@ RocketChat.API.v1.addRoute('channels.counters', { authRequired: true }, {
let msgs = null;
let latest = null;
let members = null;
let lm = null;

if (ruserId) {
if (userId) {
if (!access) {
return RocketChat.API.v1.unauthorized();
}
user = ruserId;
user = userId;
}
const room = findChannelByIdOrName({
params: this.requestParams(),
returnUsernames: true
});
const channel = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(room._id, user);
lm = channel._room.lm ? channel._room.lm : channel._room._updatedAt;
const subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(room._id, user);
const lm = room.lm ? room.lm : room._updatedAt;

if (typeof channel !== 'undefined' && channel.open) {
if (channel.ls) {
unreads = RocketChat.models.Messages.countVisibleByRoomIdBetweenTimestampsInclusive(channel.rid, channel.ls, lm);
unreadsFrom = channel.ls;
if (typeof subscription !== 'undefined' && subscription.open) {
if (subscription.ls) {
unreads = RocketChat.models.Messages.countVisibleByRoomIdBetweenTimestampsInclusive(subscription.rid, subscription.ls, lm);
unreadsFrom = subscription.ls;
}
userMentions = channel.userMentions;
userMentions = subscription.userMentions;
joined = true;
}

if (access || joined) {
msgs = room.msgs;
latest = lm;
members = room.usernames.length;
members = room.usersCount;
}

return RocketChat.API.v1.success({
Expand Down Expand Up @@ -494,28 +490,32 @@ RocketChat.API.v1.addRoute('channels.list', { authRequired: true }, {
const { sort, fields, query } = this.parseJsonQuery();
const hasPermissionToSeeAllPublicChannels = RocketChat.authz.hasPermission(this.userId, 'view-c-room');

const ourQuery = Object.assign({}, query, { t: 'c' });
const ourQuery = { ...query, t: 'c' };

if (RocketChat.authz.hasPermission(this.userId, 'view-joined-room') && !hasPermissionToSeeAllPublicChannels) {
ourQuery.usernames = {
$in: [this.user.username]
};
} else if (!hasPermissionToSeeAllPublicChannels) {
return RocketChat.API.v1.unauthorized();
if (!hasPermissionToSeeAllPublicChannels) {
if (!RocketChat.authz.hasPermission(this.userId, 'view-joined-room')) {
return RocketChat.API.v1.unauthorized();
}
const roomIds = RocketChat.models.Subscriptions.findByUserIdAndType(this.userId, 'c', { fields: { rid: 1 } }).fetch().map(s => s.rid);
ourQuery._id = { $in: roomIds };
}

const rooms = RocketChat.models.Rooms.find(ourQuery, {
const cursor = RocketChat.models.Rooms.find(ourQuery, {
sort: sort ? sort : { name: 1 },
skip: offset,
limit: count,
fields
}).fetch();
});

const total = cursor.count();

const rooms = cursor.fetch();

return RocketChat.API.v1.success({
channels: rooms,
count: rooms.length,
offset,
total: RocketChat.models.Rooms.find(ourQuery).count()
total
});
}
}
Expand All @@ -524,22 +524,19 @@ RocketChat.API.v1.addRoute('channels.list', { authRequired: true }, {
RocketChat.API.v1.addRoute('channels.list.joined', { authRequired: true }, {
get() {
const { offset, count } = this.getPaginationItems();
const { sort, fields, query } = this.parseJsonQuery();
const ourQuery = Object.assign({}, query, {
t: 'c',
'u._id': this.userId
});

let rooms = _.pluck(RocketChat.models.Subscriptions.find(ourQuery).fetch(), '_room');
const totalCount = rooms.length;
const { sort, fields } = this.parseJsonQuery();

rooms = RocketChat.models.Rooms.processQueryOptionsOnResult(rooms, {
// TODO: CACHE: Add Breacking notice since we removed the query param
const cursor = RocketChat.models.Rooms.findBySubscriptionTypeAndUserId('c', this.userId, {
sort: sort ? sort : { name: 1 },
skip: offset,
limit: count,
fields
});

const totalCount = cursor.count();
const rooms = cursor.fetch();

return RocketChat.API.v1.success({
channels: rooms,
offset,
Expand All @@ -553,38 +550,37 @@ RocketChat.API.v1.addRoute('channels.members', { authRequired: true }, {
get() {
const findResult = findChannelByIdOrName({
params: this.requestParams(),
checkedArchived: false,
returnUsernames: true
checkedArchived: false
});

if (findResult.broadcast && !RocketChat.authz.hasPermission(this.userId, 'view-broadcast-member-list')) {
return RocketChat.API.v1.unauthorized();
}

const { offset, count } = this.getPaginationItems();
const { sort } = this.parseJsonQuery();

const shouldBeOrderedDesc = Match.test(sort, Object) && Match.test(sort.username, Number) && sort.username === -1;
const { sort = {} } = this.parseJsonQuery();

let members = RocketChat.models.Rooms.processQueryOptionsOnResult(Array.from(findResult.usernames).sort(), {
const subscriptions = RocketChat.models.Subscriptions.findByRoomId(findResult._id, {
fields: { 'u._id': 1 },
sort: { 'u.username': sort.username != null ? sort.username : 1 },
skip: offset,
limit: count
});

if (shouldBeOrderedDesc) {
members = members.reverse();
}
const total = subscriptions.count();

const members = subscriptions.fetch().map(s => s.u && s.u._id);

const users = RocketChat.models.Users.find({ username: { $in: members } }, {
const users = RocketChat.models.Users.find({ _id: { $in: members } }, {
fields: { _id: 1, username: 1, name: 1, status: 1, utcOffset: 1 },
sort: sort ? sort : { username: 1 }
sort: { username: sort.username != null ? sort.username : 1 }
}).fetch();

return RocketChat.API.v1.success({
members: users,
count: users.length,
offset,
total: findResult.usernames.length
total
});
}
});
Expand All @@ -593,36 +589,67 @@ RocketChat.API.v1.addRoute('channels.messages', { authRequired: true }, {
get() {
const findResult = findChannelByIdOrName({
params: this.requestParams(),
checkedArchived: false,
returnUsernames: true
checkedArchived: false
});
const { offset, count } = this.getPaginationItems();
const { sort, fields, query } = this.parseJsonQuery();

const ourQuery = Object.assign({}, query, { rid: findResult._id });

//Special check for the permissions
if (RocketChat.authz.hasPermission(this.userId, 'view-joined-room') && !findResult.usernames.includes(this.user.username)) {
if (RocketChat.authz.hasPermission(this.userId, 'view-joined-room') && !RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(findResult._id, this.userId, { fields: { _id: 1 } })) {
return RocketChat.API.v1.unauthorized();
} else if (!RocketChat.authz.hasPermission(this.userId, 'view-c-room')) {
}
if (!RocketChat.authz.hasPermission(this.userId, 'view-c-room')) {
return RocketChat.API.v1.unauthorized();
}

const messages = RocketChat.models.Messages.find(ourQuery, {
const cursor = RocketChat.models.Messages.find(ourQuery, {
sort: sort ? sort : { ts: -1 },
skip: offset,
limit: count,
fields
}).fetch();
});

const total = cursor.count();
const messages = cursor.fetch();

return RocketChat.API.v1.success({
messages,
count: messages.length,
offset,
total: RocketChat.models.Messages.find(ourQuery).count()
total
});
}
});
// TODO: CACHE: I dont like this method( functionality and how we implemented ) its very expensive
// TODO check if this code is better or not
// RocketChat.API.v1.addRoute('channels.online', { authRequired: true }, {
// get() {
// const { query } = this.parseJsonQuery();
// const ourQuery = Object.assign({}, query, { t: 'c' });

// const room = RocketChat.models.Rooms.findOne(ourQuery);

// if (room == null) {
// return RocketChat.API.v1.failure('Channel does not exists');
// }

// const ids = RocketChat.models.Subscriptions.find({ rid: room._id }, { fields: { 'u._id': 1 } }).fetch().map(sub => sub.u._id);

// const online = RocketChat.models.Users.find({
// username: { $exists: 1 },
// _id: { $in: ids },
// status: { $in: ['online', 'away', 'busy'] }
// }, {
// fields: { username: 1 }
// }).fetch();

// return RocketChat.API.v1.success({
// online
// });
// }
// });

RocketChat.API.v1.addRoute('channels.online', { authRequired: true }, {
get() {
Expand All @@ -636,14 +663,13 @@ RocketChat.API.v1.addRoute('channels.online', { authRequired: true }, {
}

const online = RocketChat.models.Users.findUsersNotOffline({
fields: {
username: 1
}
fields: { username: 1 }
}).fetch();

const onlineInRoom = [];
online.forEach(user => {
if (room.usernames.indexOf(user.username) !== -1) {
const subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(root._id, user._id, { fields: { _id: 1 } });
if (subscription) {
onlineInRoom.push({
_id: user._id,
username: user.username
Expand Down
Loading