From 82d43f8ac0c9c34e4fa2c96e3db0e59272dfe5b0 Mon Sep 17 00:00:00 2001 From: Thomas Belin Date: Wed, 27 Sep 2023 17:33:16 +0200 Subject: [PATCH] fix: Avoid race condition when dealing with image and image placeholder [WPB-4890] (#15898) --- src/script/event/EventRepository.ts | 9 +++++++-- src/script/util/PromiseQueue.ts | 11 +++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/script/event/EventRepository.ts b/src/script/event/EventRepository.ts index adbbb5e2fa7..04aaf5bbf56 100644 --- a/src/script/event/EventRepository.ts +++ b/src/script/event/EventRepository.ts @@ -34,6 +34,7 @@ import {Asset as ProtobufAsset} from '@wireapp/protocol-messaging'; import {WebAppEvents} from '@wireapp/webapp-events'; import {getLogger, Logger} from 'Util/Logger'; +import {queue} from 'Util/PromiseQueue'; import {TIME_IN_MILLIS} from 'Util/TimeUtil'; import {ClientEvent} from './Client'; @@ -166,7 +167,11 @@ export class EventRepository { } }; - private readonly handleIncomingEvent = async (payload: HandledEventPayload, source: NotificationSource) => { + /** + * this function will process any incoming event. It is being queued in case 2 events arrive at the same time. + * Processing events should happen sequentially (thus the queue) + */ + private readonly handleIncomingEvent = queue(async (payload: HandledEventPayload, source: NotificationSource) => { try { await this.handleEvent(payload, source); } catch (error) { @@ -176,7 +181,7 @@ export class EventRepository { throw error; } } - }; + }); /** * connects to the websocket with the given account diff --git a/src/script/util/PromiseQueue.ts b/src/script/util/PromiseQueue.ts index 9499509377c..a14eed2a00e 100644 --- a/src/script/util/PromiseQueue.ts +++ b/src/script/util/PromiseQueue.ts @@ -192,3 +192,14 @@ export class PromiseQueue { } } } + +/** + * Will make sure a function is executed in order. If the function is already running, then the next payload will be queued. + * @param callback the function to queue + */ +export function queue( + callback: (...params: Params) => Promise, +): (...params: Params) => Promise { + const promiseQueue = new PromiseQueue({name: 'queue'}); + return (...params: Params) => promiseQueue.push(() => callback(...params)); +}