summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSébastien Theys <seb@odoo.com>2020-10-27 13:16:28 +0000
committerSébastien Theys <seb@odoo.com>2020-10-27 13:16:28 +0000
commite78805fc3ae9b5dbbf72667e5bd62e5c5346cc53 (patch)
tree90e6fa8d78a37ab527714cb266b4f830d33d3357
parent4d2b8dd1bef40c592215728fab6c31f192176e93 (diff)
[FIX] mail, im_livechat: avoid artificially delaying messaging
Don't delay the insert of partners or channels until it actually takes too much time. Don't await `_initMentionPartnerSuggestions` as it is just nice to have. task-2371485 closes odoo/odoo#60826 Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
-rw-r--r--addons/im_livechat/static/src/models/messaging_initializer/messaging_initializer.js8
-rw-r--r--addons/mail/static/src/models/messaging_initializer/messaging_initializer.js21
-rw-r--r--addons/mail/static/src/utils/utils.js20
3 files changed, 31 insertions, 18 deletions
diff --git a/addons/im_livechat/static/src/models/messaging_initializer/messaging_initializer.js b/addons/im_livechat/static/src/models/messaging_initializer/messaging_initializer.js
index 634fbb5dbfe..56e02d9b5de 100644
--- a/addons/im_livechat/static/src/models/messaging_initializer/messaging_initializer.js
+++ b/addons/im_livechat/static/src/models/messaging_initializer/messaging_initializer.js
@@ -2,6 +2,7 @@ odoo.define('im_livechat/static/src/models/messaging_initializer/messaging_initi
'use strict';
const { registerInstancePatchModel } = require('mail/static/src/model/model_core.js');
+const { executeGracefully } = require('mail/static/src/utils/utils.js');
registerInstancePatchModel('mail.messaging_initializer', 'im_livechat/static/src/models/messaging_initializer/messaging_initializer.js', {
@@ -16,10 +17,7 @@ registerInstancePatchModel('mail.messaging_initializer', 'im_livechat/static/src
async _initChannels(initMessagingData) {
await this.async(() => this._super(initMessagingData));
const { channel_livechat = [] } = initMessagingData;
- for (const data of channel_livechat) {
- // there might be a lot of channels, insert each of them one by
- // one asynchronously to avoid blocking the UI
- await this.async(() => new Promise(resolve => setTimeout(resolve)));
+ return executeGracefully(channel_livechat.map(data => () => {
const channel = this.env.models['mail.thread'].insert(
this.env.models['mail.thread'].convertData(data),
);
@@ -28,7 +26,7 @@ registerInstancePatchModel('mail.messaging_initializer', 'im_livechat/static/src
if (!channel.isPinned) {
channel.pin();
}
- }
+ }));
},
});
diff --git a/addons/mail/static/src/models/messaging_initializer/messaging_initializer.js b/addons/mail/static/src/models/messaging_initializer/messaging_initializer.js
index da2f51757be..c22c197e87c 100644
--- a/addons/mail/static/src/models/messaging_initializer/messaging_initializer.js
+++ b/addons/mail/static/src/models/messaging_initializer/messaging_initializer.js
@@ -3,6 +3,7 @@ odoo.define('mail/static/src/models/messaging_initializer/messaging_initializer.
const { registerNewModel } = require('mail/static/src/model/model_core.js');
const { one2one } = require('mail/static/src/model/model_field.js');
+const { executeGracefully } = require('mail/static/src/utils/utils.js');
function factory(dependencies) {
@@ -118,7 +119,7 @@ function factory(dependencies) {
// various suggestions in no particular order
this._initCannedResponses(shortcodes);
this._initCommands(commands);
- await this.async(() => this._initMentionPartnerSuggestions(mention_partner_suggestions));
+ this._initMentionPartnerSuggestions(mention_partner_suggestions);
// channels when the rest of messaging is ready
await this.async(() => this._initChannels(channel_slots));
// failures after channels
@@ -149,10 +150,7 @@ function factory(dependencies) {
channel_private_group = [],
} = {}) {
const channelsData = channel_channel.concat(channel_direct_message, channel_private_group);
- for (const channelData of channelsData) {
- // there might be a lot of channels, insert each of them one by
- // one asynchronously to avoid blocking the UI
- await this.async(() => new Promise(resolve => setTimeout(resolve)));
+ return executeGracefully(channelsData.map(channelData => () => {
const convertedData = this.env.models['mail.thread'].convertData(channelData);
if (!convertedData.members) {
// channel_info does not return all members of channel for
@@ -171,7 +169,7 @@ function factory(dependencies) {
if (!channel.isPinned) {
channel.pin();
}
- }
+ }));
}
/**
@@ -233,15 +231,12 @@ function factory(dependencies) {
* @param {Object[]} mentionPartnerSuggestionsData
*/
async _initMentionPartnerSuggestions(mentionPartnerSuggestionsData) {
- for (const suggestions of mentionPartnerSuggestionsData) {
- for (const suggestion of suggestions) {
- // there might be a lot of partners, insert each of them one
- // by one asynchronously to avoid blocking the UI
- await this.async(() => new Promise(resolve => setTimeout(resolve)));
+ return executeGracefully(mentionPartnerSuggestionsData.map(suggestions => () => {
+ return executeGracefully(suggestions.map(suggestion => () => {
const { email, id, name } = suggestion;
this.env.models['mail.partner'].insert({ email, id, name });
- }
- }
+ }));
+ }));
}
/**
diff --git a/addons/mail/static/src/utils/utils.js b/addons/mail/static/src/utils/utils.js
index 8112eeca980..f502fc8f326 100644
--- a/addons/mail/static/src/utils/utils.js
+++ b/addons/mail/static/src/utils/utils.js
@@ -15,6 +15,25 @@ const classPatchMap = new WeakMap();
const eventHandledWeakMap = new WeakMap();
/**
+ * Executes the provided functions in order, but with a potential delay between
+ * them if they take too much time. This is done in order to avoid blocking the
+ * main thread for too long.
+ *
+ * @param {function[]} functions
+ * @param {integer} [maxTimeFrame=100] time (in ms) until a delay is introduced
+ */
+async function executeGracefully(functions, maxTimeFrame = 100) {
+ let startDate = new Date();
+ for (const func of functions) {
+ if (new Date() - startDate > maxTimeFrame) {
+ await new Promise(resolve => setTimeout(resolve));
+ startDate = new Date();
+ }
+ await func();
+ }
+}
+
+/**
* Returns whether the given event has been handled with the given markName.
*
* @param {Event} ev
@@ -147,6 +166,7 @@ function unpatchInstanceMethods(Class, patchName) {
//------------------------------------------------------------------------------
return {
+ executeGracefully,
isEventHandled,
markEventHandled,
nextTick,