[IMP] mail: introduce Messaging/executeGracefully
- Made executeGracefully in messaging so it can have specific behaviour in qunit tests (no timeout) - guard all usages of `executeGracefully` in case current record is deleted (e.g. during test teardown). Task-2976295 Part-of: odoo/odoo#99556
This commit is contained in:
@@ -1,10 +1,9 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { registerModel } from '@mail/model/model_core';
|
||||
import { attr, many } from '@mail/model/model_field';
|
||||
import { many } from '@mail/model/model_field';
|
||||
import { insert } from '@mail/model/model_field_command';
|
||||
import { emojiCategoriesData, emojisData } from '@mail/models_data/emoji_data';
|
||||
import { executeGracefully } from '@mail/utils/utils';
|
||||
|
||||
registerModel({
|
||||
name: 'EmojiRegistry',
|
||||
@@ -15,7 +14,7 @@ registerModel({
|
||||
},
|
||||
recordMethods: {
|
||||
async _populateFromEmojiData(dataCategories, dataEmojis) {
|
||||
await executeGracefully(dataCategories.map(category => () => {
|
||||
await this.messaging.executeGracefully(dataCategories.map(category => () => {
|
||||
if (!this.exists()) {
|
||||
return;
|
||||
}
|
||||
@@ -29,8 +28,10 @@ registerModel({
|
||||
}),
|
||||
});
|
||||
}));
|
||||
this.update({ allEmojiCount: dataEmojis.length }); // Set the total number of emojis to the category before all emojis are processed and created.
|
||||
await executeGracefully(dataEmojis.map(emojiData => () => {
|
||||
if (!this.exists()) {
|
||||
return;
|
||||
}
|
||||
await this.messaging.executeGracefully(dataEmojis.map(emojiData => () => {
|
||||
if (!this.exists()) {
|
||||
return;
|
||||
}
|
||||
@@ -59,9 +60,6 @@ registerModel({
|
||||
inverse: 'emojiRegistry',
|
||||
sort: '_sortAllCategories',
|
||||
}),
|
||||
allEmojiCount: attr({
|
||||
default: 0,
|
||||
}),
|
||||
allEmojis: many('Emoji', {
|
||||
inverse: 'emojiRegistry',
|
||||
sort: '_sortAllEmojis'
|
||||
|
||||
@@ -37,6 +37,23 @@ registerModel({
|
||||
this.update({ isInitialized: true });
|
||||
this.initializedPromise.resolve();
|
||||
},
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
async executeGracefully(functions) {
|
||||
let date = new Date();
|
||||
for (const func of functions) {
|
||||
if (new Date() - date > 100) {
|
||||
await new Promise(resolve => setTimeout(resolve, this.isInQUnitTest ? 0 : 50));
|
||||
date = new Date();
|
||||
}
|
||||
await func();
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Open the form view of the record with provided id and model.
|
||||
* Gets the chat with the provided person and returns it.
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { registerModel } from '@mail/model/model_core';
|
||||
import { executeGracefully } from '@mail/utils/utils';
|
||||
import { insert } from '@mail/model/model_field_command';
|
||||
|
||||
registerModel({
|
||||
@@ -118,7 +117,10 @@ registerModel({
|
||||
* @param {Object[]} channelsData
|
||||
*/
|
||||
async _initChannels(channelsData) {
|
||||
return executeGracefully(channelsData.map(channelData => () => {
|
||||
return this.messaging.executeGracefully(channelsData.map(channelData => () => {
|
||||
if (!this.exists()) {
|
||||
return;
|
||||
}
|
||||
const convertedData = this.messaging.models['Thread'].convertData(channelData);
|
||||
const channel = this.messaging.models['Thread'].insert(
|
||||
Object.assign({ model: 'mail.channel' }, convertedData)
|
||||
@@ -173,7 +175,10 @@ registerModel({
|
||||
* @param {Object[]} mailFailuresData
|
||||
*/
|
||||
async _initMailFailures(mailFailuresData) {
|
||||
await executeGracefully(mailFailuresData.map(messageData => () => {
|
||||
await this.messaging.executeGracefully(mailFailuresData.map(messageData => () => {
|
||||
if (!this.exists()) {
|
||||
return;
|
||||
}
|
||||
const message = this.messaging.models['Message'].insert(
|
||||
this.messaging.models['Message'].convertData(messageData)
|
||||
);
|
||||
|
||||
@@ -21,25 +21,6 @@ function cleanSearchTerm(searchTerm) {
|
||||
return unaccent(searchTerm.toLowerCase());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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, 50));
|
||||
startDate = new Date();
|
||||
}
|
||||
await func();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given event has been handled with the given markName.
|
||||
*
|
||||
@@ -83,7 +64,6 @@ async function nextTick() {
|
||||
|
||||
export {
|
||||
cleanSearchTerm,
|
||||
executeGracefully,
|
||||
isEventHandled,
|
||||
markEventHandled,
|
||||
nextTick,
|
||||
|
||||
Reference in New Issue
Block a user