[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:
@@ -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 });
|
||||
}
|
||||
}
|
||||
}));
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user