From af2a27c730fb0e0a4112803f7e01969ec3c72c0e Mon Sep 17 00:00:00 2001 From: Rodrigo Nascimento <rodrigoknascimento@gmail.com> Date: Mon, 21 Mar 2016 20:45:40 -0300 Subject: [PATCH] Improve sendMessage performance by 300% --- packages/rocketchat-lib/lib/callbacks.coffee | 22 ++++-- .../server/lib/notifyUsersOnMessage.js | 4 +- .../server/lib/sendNotificationsOnMessage.js | 72 ++++++++++--------- .../rocketchat-lib/server/models/Users.coffee | 8 +++ .../server/models/Subscriptions.js | 67 ++++++++++------- 5 files changed, 108 insertions(+), 65 deletions(-) diff --git a/packages/rocketchat-lib/lib/callbacks.coffee b/packages/rocketchat-lib/lib/callbacks.coffee index e9f8ffc8662..ebbe30ad649 100644 --- a/packages/rocketchat-lib/lib/callbacks.coffee +++ b/packages/rocketchat-lib/lib/callbacks.coffee @@ -6,6 +6,8 @@ ### RocketChat.callbacks = {} +RocketChat.callbacks.showTime = false + ### # Callback priorities ### @@ -19,7 +21,6 @@ RocketChat.callbacks.priority = # @param {String} hook - The name of the hook # @param {Function} callback - The callback function ### - RocketChat.callbacks.add = (hook, callback, priority, id) -> # if callback array doesn't exist yet, initialize it priority ?= RocketChat.callbacks.priority.MEDIUM @@ -28,12 +29,16 @@ RocketChat.callbacks.add = (hook, callback, priority, id) -> callback.priority = priority callback.id = id or Random.id() RocketChat.callbacks[hook] ?= [] - + + if RocketChat.callbacks.showTime is true + err = new Error + callback.stack = err.stack + # Avoid adding the same callback twice for cb in RocketChat.callbacks[hook] if cb.id is callback.id return - + RocketChat.callbacks[hook].push callback return @@ -62,7 +67,16 @@ RocketChat.callbacks.run = (hook, item, constant) -> # if the hook exists, and contains callbacks to run _.sortBy(callbacks, (callback) -> return callback.priority or RocketChat.callbacks.priority.MEDIUM).reduce (result, callback) -> # console.log(callback.name); - callback result, constant + if RocketChat.callbacks.showTime is true + time = Date.now() + + callbackResult = callback result, constant + + if RocketChat.callbacks.showTime is true + console.log hook, Date.now() - time + console.log callback.stack.split('\n')[2] + + return callbackResult , item else # else, just return the item unchanged diff --git a/packages/rocketchat-lib/server/lib/notifyUsersOnMessage.js b/packages/rocketchat-lib/server/lib/notifyUsersOnMessage.js index 59de2faa8ec..9a7547219b5 100644 --- a/packages/rocketchat-lib/server/lib/notifyUsersOnMessage.js +++ b/packages/rocketchat-lib/server/lib/notifyUsersOnMessage.js @@ -13,7 +13,7 @@ RocketChat.callbacks.add('afterSaveMessage', function(message, room) { * @returns {boolean} */ function messageContainsHighlight(message, highlights) { - if (! highlights || highlights.length == 0) { return false; } + if (! highlights || highlights.length === 0) { return false; } var has = false; highlights.some(function (highlight) { @@ -36,7 +36,7 @@ RocketChat.callbacks.add('afterSaveMessage', function(message, room) { mentionIds = []; highlightsIds = []; toAll = false; - highlights = RocketChat.models.Users.findUsersByUsernames(room.usernames, { fields: { '_id': 1, 'settings.preferences.highlights': 1 }}).fetch(); + highlights = RocketChat.models.Users.findUsersByUsernamesWithHighlights(room.usernames, { fields: { '_id': 1, 'settings.preferences.highlights': 1 }}).fetch(); if (message.mentions != null) { message.mentions.forEach(function(mention) { diff --git a/packages/rocketchat-lib/server/lib/sendNotificationsOnMessage.js b/packages/rocketchat-lib/server/lib/sendNotificationsOnMessage.js index f03ac3e2b69..1cd04f8fc10 100644 --- a/packages/rocketchat-lib/server/lib/sendNotificationsOnMessage.js +++ b/packages/rocketchat-lib/server/lib/sendNotificationsOnMessage.js @@ -1,3 +1,5 @@ +/* globals Push */ + RocketChat.callbacks.add('afterSaveMessage', function(message, room) { // skips this callback if the message was edited if (message.editedAt) { @@ -9,7 +11,14 @@ RocketChat.callbacks.add('afterSaveMessage', function(message, room) { /* Increment unread couter if direct messages */ - var indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; + var indexOf = [].indexOf || function(item) { + for (var i = 0, l = this.length; i < l; i++) { + if (i in this && this[i] === item) { + return i; + } + } + return -1; + }; var settings, desktopMentionIds, i, j, len, len1, highlights, mentionIds, highlightsIds, usersWithHighlights, mobileMentionIds, ref, ref1, toAll, userIdsToNotify, userIdsToPushNotify, userOfMention, userOfMentionId, usersOfDesktopMentions, usersOfMentionId, usersOfMentionItem, usersOfMobileMentions; @@ -39,7 +48,7 @@ RocketChat.callbacks.add('afterSaveMessage', function(message, room) { * @returns {boolean} */ function messageContainsHighlight(message, highlights) { - if (! highlights || highlights.length == 0) { return false; } + if (! highlights || highlights.length === 0) { return false; } var has = false; highlights.some(function (highlight) { @@ -55,30 +64,26 @@ RocketChat.callbacks.add('afterSaveMessage', function(message, room) { settings = {}; - settings.alwaysNotifyDesktopUsers = _.compact(_.map(RocketChat.models.Subscriptions.findAlwaysNotifyDesktopUsersByRoomId(room._id).fetch(), function(subscription) { - var ref; - return subscription != null ? (ref = subscription.u) != null ? ref._id : void 0 : void 0; - })); - - settings.dontNotifyDesktopUsers = _.compact(_.map(RocketChat.models.Subscriptions.findDontNotifyDesktopUsersByRoomId(room._id).fetch(), function(subscription) { - var ref; - return subscription != null ? (ref = subscription.u) != null ? ref._id : void 0 : void 0; - })); - - settings.alwaysNotifyMobileUsers = _.compact(_.map(RocketChat.models.Subscriptions.findAlwaysNotifyMobileUsersByRoomId(room._id).fetch(), function(subscription) { - var ref; - return subscription != null ? (ref = subscription.u) != null ? ref._id : void 0 : void 0; - })); - - settings.dontNotifyMobileUsers = _.compact(_.map(RocketChat.models.Subscriptions.findDontNotifyMobileUsersByRoomId(room._id).fetch(), function(subscription) { - var ref; - return subscription != null ? (ref = subscription.u) != null ? ref._id : void 0 : void 0; - })); + settings.alwaysNotifyDesktopUsers = []; + settings.dontNotifyDesktopUsers = []; + settings.alwaysNotifyMobileUsers = []; + settings.dontNotifyMobileUsers = []; + RocketChat.models.Subscriptions.findNotificationPreferencesByRoom(room._id).forEach(function(subscription) { + if (subscription.desktopNotifications === 'all') { + settings.alwaysNotifyDesktopUsers.push(subscription.u._id); + } else if (subscription.desktopNotifications === 'nothing') { + settings.dontNotifyDesktopUsers.push(subscription.u._id); + } else if (subscription.mobilePushNotifications === 'all') { + settings.alwaysNotifyMobileUsers.push(subscription.u._id); + } else if (subscription.mobilePushNotifications === 'nothing') { + settings.dontNotifyMobileUsers.push(subscription.u._id); + } + }); userIdsToNotify = []; userIdsToPushNotify = []; usersWithHighlights = []; - highlights = RocketChat.models.Users.findUsersByUsernames(room.usernames, { fields: { '_id': 1, 'settings.preferences.highlights': 1 }}).fetch(); + highlights = RocketChat.models.Users.findUsersByUsernamesWithHighlights(room.usernames, { fields: { '_id': 1, 'settings.preferences.highlights': 1 }}).fetch(); highlights.forEach(function (user) { if (user && user.settings && user.settings.preferences && messageContainsHighlight(message, user.settings.preferences.highlights)) { @@ -86,19 +91,22 @@ RocketChat.callbacks.add('afterSaveMessage', function(message, room) { } }); + let push_message; //Set variables depending on Push Notification settings if (RocketChat.settings.get('Push_show_message')) { - push_message = message.msg + push_message = message.msg; } else { - push_message = ' ' + push_message = ' '; } + let push_username; + let push_room; if (RocketChat.settings.get('Push_show_username_room')) { - push_username = "@" + user.username - push_room = "#" + room.name + " " + push_username = '@' + user.username; + push_room = '#' + room.name + ' '; } else { - push_username = ' ' - push_room = ' ' + push_username = ' '; + push_room = ' '; } if ((room.t == null) || room.t === 'd') { @@ -113,7 +121,7 @@ RocketChat.callbacks.add('afterSaveMessage', function(message, room) { }); if ((userOfMention != null) && canBeNotified(userOfMentionId, 'mobile')) { RocketChat.Notifications.notifyUser(userOfMention._id, 'notification', { - title: "@" + user.username, + title: '@' + user.username, text: message.msg, payload: { rid: message.rid, @@ -131,7 +139,7 @@ RocketChat.callbacks.add('afterSaveMessage', function(message, room) { text: push_message, apn: { // ternary operator - text: push_username + ((push_username != ' ' && push_message != ' ') ? ":\n" : '') + push_message + text: push_username + ((push_username !== ' ' && push_message !== ' ') ? ':\n' : '') + push_message }, badge: 1, sound: 'chime', @@ -241,7 +249,7 @@ RocketChat.callbacks.add('afterSaveMessage', function(message, room) { for (j = 0, len1 = userIdsToNotify.length; j < len1; j++) { usersOfMentionId = userIdsToNotify[j]; RocketChat.Notifications.notifyUser(usersOfMentionId, 'notification', { - title: "@" + user.username + " @ #" + room.name, + title: '@' + user.username + ' @ #' + room.name, text: message.msg, payload: { rid: message.rid, @@ -261,7 +269,7 @@ RocketChat.callbacks.add('afterSaveMessage', function(message, room) { text: push_message, apn: { // ternary operator - text: push_room + push_username + ((push_username != ' ' && push_room != ' ' && push_message != ' ') ? ":\n" : '') + push_message + text: push_room + push_username + ((push_username !== ' ' && push_room !== ' ' && push_message !== ' ') ? ':\n' : '') + push_message }, badge: 1, sound: 'chime', diff --git a/packages/rocketchat-lib/server/models/Users.coffee b/packages/rocketchat-lib/server/models/Users.coffee index 012f91aaab7..0186d5a8756 100644 --- a/packages/rocketchat-lib/server/models/Users.coffee +++ b/packages/rocketchat-lib/server/models/Users.coffee @@ -62,6 +62,14 @@ RocketChat.models.Users = new class extends RocketChat.models._Base return @find query, options + findUsersByUsernamesWithHighlights: (username, options) -> + query = + username: username + 'settings.preferences.highlights': + $exists: true + + return @find query, options + findActiveByUsernameRegexWithExceptions: (username, exceptions = [], options = {}) -> if not _.isArray exceptions exceptions = [ exceptions ] diff --git a/packages/rocketchat-push-notifications/server/models/Subscriptions.js b/packages/rocketchat-push-notifications/server/models/Subscriptions.js index c421bcd634f..2a15a3be81b 100644 --- a/packages/rocketchat-push-notifications/server/models/Subscriptions.js +++ b/packages/rocketchat-push-notifications/server/models/Subscriptions.js @@ -1,80 +1,93 @@ RocketChat.models.Subscriptions.updateDesktopNotificationsById = function(_id, desktopNotifications) { - query = { + const query = { _id: _id - } + }; - update = { + const update = { $set: { desktopNotifications: desktopNotifications } - } + }; return this.update(query, update); -} +}; RocketChat.models.Subscriptions.updateMobilePushNotificationsById = function(_id, mobilePushNotifications) { - query = { + const query = { _id: _id - } + }; - update = { + const update = { $set: { mobilePushNotifications: mobilePushNotifications } - } + }; return this.update(query, update); -} +}; RocketChat.models.Subscriptions.updateEmailNotificationsById = function(_id, emailNotifications) { - query = { + const query = { _id: _id - } + }; - update = { + const update = { $set: { emailNotifications: emailNotifications } - } + }; return this.update(query, update); -} +}; RocketChat.models.Subscriptions.findAlwaysNotifyDesktopUsersByRoomId = function(roomId) { - query = { + const query = { rid: roomId, desktopNotifications: 'all' - } + }; return this.find(query); -} +}; RocketChat.models.Subscriptions.findDontNotifyDesktopUsersByRoomId = function(roomId) { - query = { + const query = { rid: roomId, desktopNotifications: 'nothing' - } + }; return this.find(query); -} +}; RocketChat.models.Subscriptions.findAlwaysNotifyMobileUsersByRoomId = function(roomId) { - query = { + const query = { rid: roomId, mobilePushNotifications: 'all' - } + }; return this.find(query); -} +}; RocketChat.models.Subscriptions.findDontNotifyMobileUsersByRoomId = function(roomId) { - query = { + const query = { rid: roomId, mobilePushNotifications: 'nothing' - } + }; return this.find(query); -} +}; + +RocketChat.models.Subscriptions.findNotificationPreferencesByRoom = function(roomId) { + const query = { + rid: roomId, + 'u._id': {$exists: true}, + $or: [ + {desktopNotifications: {$exists: true}}, + {mobilePushNotifications: {$exists: true}} + ] + }; + + return this.find(query); +}; RocketChat.models.Subscriptions.findWithSendEmailByRoomId = function(roomId) { var query = { -- GitLab