From bd8e7635394139f95daf17c03d9246c175d45eba Mon Sep 17 00:00:00 2001 From: JC Brand Date: Tue, 27 Oct 2020 22:48:22 +0100 Subject: [PATCH] Only create new message models once messages have been fetched Fixes #2241 --- src/headless/converse-chat.js | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/headless/converse-chat.js b/src/headless/converse-chat.js index f61fd977cf..edcba628da 100644 --- a/src/headless/converse-chat.js +++ b/src/headless/converse-chat.js @@ -355,6 +355,7 @@ converse.plugins.add('converse-chat', { initMessages () { this.messages = new this.messagesCollection(); + this.messages.fetched = u.getResolveablePromise(); this.messages.chatbox = this; this.messages.browserStorage = _converse.createStore(this.getMessagesCacheKey()); this.listenTo(this.messages, 'change:upload', message => { @@ -380,11 +381,11 @@ converse.plugins.add('converse-chat', { }, fetchMessages () { - if (this.messages.fetched) { + if (this.messages.fetched_flag) { log.info(`Not re-fetching messages for ${this.get('jid')}`); return; } - this.messages.fetched = u.getResolveablePromise(); + this.messages.fetched_flag = true; const resolve = this.messages.fetched.resolve; this.messages.fetch({ 'add': true, @@ -439,8 +440,9 @@ converse.plugins.add('converse-chat', { * @param { Promise } attrs - A promise which resolves to the message attributes */ queueMessage (attrs) { - this.msg_chain = (this.msg_chain || this.messages.fetched); - this.msg_chain = this.msg_chain.then(() => this.onMessage(attrs)); + this.msg_chain = (this.msg_chain || this.messages.fetched) + .then(() => this.onMessage(attrs)) + .catch(e => log.error(e)); return this.msg_chain; }, @@ -485,7 +487,9 @@ converse.plugins.add('converse-chat', { log.error(e); } finally { delete this.msg_chain; + delete this.msg_creation_chain; delete this.messages.fetched; + delete this.messages.fetched_flag; } }, @@ -1009,12 +1013,18 @@ converse.plugins.add('converse-chat', { }, /** + * Queue the creation of a message, to make sure that we don't run + * into a race condition whereby we're creating a new message + * before the collection has been fetched. * @async * @private - * @method _converse.ChatBox#createMessage + * @method _converse.ChatRoom#queueMessageCreation + * @param { Object } attrs */ - createMessage (attrs, options) { - return this.messages.create(attrs, Object.assign({'wait': true, 'promise':true}, options)).catch(e => log.error(e)); + async createMessage (attrs, options) { + this.msg_creation_chain = (this.msg_creation_chain || this.messages.fetched); + await this.msg_creation_chain; + return this.messages.create(attrs, Object.assign({'wait': true, 'promise':true}, options)); }, /**