From b9a2e626020bb6d479ed91b2959d371fae6171eb Mon Sep 17 00:00:00 2001 From: Jonathan Rainville Date: Wed, 3 May 2023 14:23:02 -0400 Subject: [PATCH] fix(message/service): fix msg not appearing in new chat because of race Fixes #10340 Fixes a race condition when receiving a message in a channel that doesn't exist yet (for example in a delete 1-1 chat). What happens is that the status-go signal contains both the message and the chat. Both are handled by different services, so there was a race between the two of them. If the chat service handled the chat first, then the message was added correctly, but in the case of the message service handling it first, it would try to add the message to a chat that doesn't exist yet, so it wouldn't work. I also cleaned the ChatUpdateArgs by removing the messages arg that was not used anywhere and also was a bit counter-intuitive. Why did a Chat arg have messages? --- src/app/boot/app_controller.nim | 8 +++++++- src/app_service/service/chat/service.nim | 9 ++++----- src/app_service/service/message/service.nim | 10 ++++++++++ 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/app/boot/app_controller.nim b/src/app/boot/app_controller.nim index d5a2459a74..e4cf47600a 100644 --- a/src/app/boot/app_controller.nim +++ b/src/app/boot/app_controller.nim @@ -183,7 +183,13 @@ proc newAppController*(statusFoundation: StatusFoundation): AppController = result.tokenService, result.networkService ) result.messageService = message_service.newService( - statusFoundation.events, statusFoundation.threadpool, result.contactsService, result.tokenService, result.walletAccountService, result.networkService + statusFoundation.events, + statusFoundation.threadpool, + result.chatService, + result.contactsService, + result.tokenService, + result.walletAccountService, + result.networkService, ) result.communityService = community_service.newService(statusFoundation.events, statusFoundation.threadpool, result.chatService, result.activityCenterService, result.messageService) diff --git a/src/app_service/service/chat/service.nim b/src/app_service/service/chat/service.nim index abf3b57f9e..64cd8381c2 100644 --- a/src/app_service/service/chat/service.nim +++ b/src/app_service/service/chat/service.nim @@ -36,7 +36,6 @@ type ChatUpdateArgs* = ref object of Args chats*: seq[ChatDto] - messages*: seq[MessageDto] CreatedChatArgs* = ref object of Args chat*: ChatDto @@ -151,7 +150,7 @@ QtObject: self.events.emit(SIGNAL_CHAT_MEMBERS_CHANGED, ChatMembersChangedArgs(chatId: chatDto.id, members: chatDto.members)) self.updateOrAddChat(chatDto) - self.events.emit(SIGNAL_CHAT_UPDATE, ChatUpdateArgs(messages: receivedData.messages, chats: chats)) + self.events.emit(SIGNAL_CHAT_UPDATE, ChatUpdateArgs(chats: chats)) if (receivedData.clearedHistories.len > 0): for clearedHistoryDto in receivedData.clearedHistories: @@ -357,12 +356,12 @@ QtObject: break proc processUpdateForTransaction*(self: Service, messageId: string, response: RpcResponse[JsonNode]) = - var (chats, messages) = self.processMessageUpdateAfterSend(response) + var (chats, _) = self.processMessageUpdateAfterSend(response) self.events.emit(SIGNAL_MESSAGE_DELETED, MessageArgs(id: messageId, channel: chats[0].id)) proc emitUpdate(self: Service, response: RpcResponse[JsonNode]) = - var (chats, messages) = self.parseChatResponse(response) - self.events.emit(SIGNAL_CHAT_UPDATE, ChatUpdateArgs(messages: messages, chats: chats)) + var (chats, _) = self.parseChatResponse(response) + self.events.emit(SIGNAL_CHAT_UPDATE, ChatUpdateArgs(chats: chats)) proc getAllChats*(self: Service): seq[ChatDto] = return toSeq(self.chats.values) diff --git a/src/app_service/service/message/service.nim b/src/app_service/service/message/service.nim index 9b858edfcc..bfd7522308 100644 --- a/src/app_service/service/message/service.nim +++ b/src/app_service/service/message/service.nim @@ -7,6 +7,7 @@ import ../../../app/global/global_singleton import ../../../backend/accounts as status_accounts import ../../../backend/messages as status_go import ../contacts/service as contact_service +import ../chat/service as chat_service import ../token/service as token_service import ../network/service as network_service import ../wallet_account/service as wallet_account_service @@ -131,6 +132,7 @@ QtObject: type Service* = ref object of QObject events: EventEmitter threadpool: ThreadPool + chatService: chat_service.Service contactService: contact_service.Service tokenService: token_service.Service walletAccountService: wallet_account_service.Service @@ -145,6 +147,7 @@ QtObject: proc newService*( events: EventEmitter, threadpool: ThreadPool, + chatService: chat_service.Service, contactService: contact_service.Service, tokenService: token_service.Service, walletAccountService: wallet_account_service.Service, @@ -154,6 +157,7 @@ QtObject: result.QObject.setup result.events = events result.threadpool = threadpool + result.chatService = chatService result.contactService = contactService result.tokenService = tokenService result.walletAccountService = walletAccountService @@ -271,6 +275,12 @@ QtObject: if(chats[i].chatType == ChatType.OneToOne and not self.contactService.getContactById(chatId).isContact): continue + + if self.chatService.getChatById(chats[i].id, showWarning = false).id == "": + # Chat is not present in the chat cache. We need to add it first + self.chatService.updateOrAddChat(chats[i]) + self.events.emit(SIGNAL_CHAT_UPDATE, ChatUpdateArgs(chats: chats)) + var chatMessages: seq[MessageDto] for msg in messages: if(msg.localChatId != chatId):