[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#60911

X-original-commit: e78805fc3ae9b5dbbf72667e5bd62e5c5346cc53
Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
This commit is contained in:
Sébastien Theys
2020-10-28 14:55:47 +00:00
parent fb786296a5
commit abb7d2dab9
3 changed files with 31 additions and 18 deletions
@@ -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();
}
}
}));
},
});
@@ -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 });
}
}
}));
}));
}
/**
+20
View File
@@ -14,6 +14,25 @@ const {
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.
*
@@ -147,6 +166,7 @@ function unpatchInstanceMethods(Class, patchName) {
//------------------------------------------------------------------------------
return {
executeGracefully,
isEventHandled,
markEventHandled,
nextTick,