[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:
Alexandre Kühn
2022-09-08 12:46:37 +02:00
committed by tsm-odoo
parent c4e84115c2
commit d8ba2ce234
4 changed files with 31 additions and 31 deletions
@@ -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)
);
-20
View File
@@ -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,