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?
This commit is contained in:
Jonathan Rainville 2023-05-03 14:23:02 -04:00
parent 0e5c566dcd
commit b9a2e62602
3 changed files with 21 additions and 6 deletions

View File

@ -183,7 +183,13 @@ proc newAppController*(statusFoundation: StatusFoundation): AppController =
result.tokenService, result.networkService result.tokenService, result.networkService
) )
result.messageService = message_service.newService( 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, result.communityService = community_service.newService(statusFoundation.events,
statusFoundation.threadpool, result.chatService, result.activityCenterService, result.messageService) statusFoundation.threadpool, result.chatService, result.activityCenterService, result.messageService)

View File

@ -36,7 +36,6 @@ type
ChatUpdateArgs* = ref object of Args ChatUpdateArgs* = ref object of Args
chats*: seq[ChatDto] chats*: seq[ChatDto]
messages*: seq[MessageDto]
CreatedChatArgs* = ref object of Args CreatedChatArgs* = ref object of Args
chat*: ChatDto chat*: ChatDto
@ -151,7 +150,7 @@ QtObject:
self.events.emit(SIGNAL_CHAT_MEMBERS_CHANGED, ChatMembersChangedArgs(chatId: chatDto.id, members: chatDto.members)) self.events.emit(SIGNAL_CHAT_MEMBERS_CHANGED, ChatMembersChangedArgs(chatId: chatDto.id, members: chatDto.members))
self.updateOrAddChat(chatDto) 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): if (receivedData.clearedHistories.len > 0):
for clearedHistoryDto in receivedData.clearedHistories: for clearedHistoryDto in receivedData.clearedHistories:
@ -357,12 +356,12 @@ QtObject:
break break
proc processUpdateForTransaction*(self: Service, messageId: string, response: RpcResponse[JsonNode]) = 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)) self.events.emit(SIGNAL_MESSAGE_DELETED, MessageArgs(id: messageId, channel: chats[0].id))
proc emitUpdate(self: Service, response: RpcResponse[JsonNode]) = proc emitUpdate(self: Service, response: RpcResponse[JsonNode]) =
var (chats, messages) = self.parseChatResponse(response) var (chats, _) = self.parseChatResponse(response)
self.events.emit(SIGNAL_CHAT_UPDATE, ChatUpdateArgs(messages: messages, chats: chats)) self.events.emit(SIGNAL_CHAT_UPDATE, ChatUpdateArgs(chats: chats))
proc getAllChats*(self: Service): seq[ChatDto] = proc getAllChats*(self: Service): seq[ChatDto] =
return toSeq(self.chats.values) return toSeq(self.chats.values)

View File

@ -7,6 +7,7 @@ import ../../../app/global/global_singleton
import ../../../backend/accounts as status_accounts import ../../../backend/accounts as status_accounts
import ../../../backend/messages as status_go import ../../../backend/messages as status_go
import ../contacts/service as contact_service import ../contacts/service as contact_service
import ../chat/service as chat_service
import ../token/service as token_service import ../token/service as token_service
import ../network/service as network_service import ../network/service as network_service
import ../wallet_account/service as wallet_account_service import ../wallet_account/service as wallet_account_service
@ -131,6 +132,7 @@ QtObject:
type Service* = ref object of QObject type Service* = ref object of QObject
events: EventEmitter events: EventEmitter
threadpool: ThreadPool threadpool: ThreadPool
chatService: chat_service.Service
contactService: contact_service.Service contactService: contact_service.Service
tokenService: token_service.Service tokenService: token_service.Service
walletAccountService: wallet_account_service.Service walletAccountService: wallet_account_service.Service
@ -145,6 +147,7 @@ QtObject:
proc newService*( proc newService*(
events: EventEmitter, events: EventEmitter,
threadpool: ThreadPool, threadpool: ThreadPool,
chatService: chat_service.Service,
contactService: contact_service.Service, contactService: contact_service.Service,
tokenService: token_service.Service, tokenService: token_service.Service,
walletAccountService: wallet_account_service.Service, walletAccountService: wallet_account_service.Service,
@ -154,6 +157,7 @@ QtObject:
result.QObject.setup result.QObject.setup
result.events = events result.events = events
result.threadpool = threadpool result.threadpool = threadpool
result.chatService = chatService
result.contactService = contactService result.contactService = contactService
result.tokenService = tokenService result.tokenService = tokenService
result.walletAccountService = walletAccountService result.walletAccountService = walletAccountService
@ -271,6 +275,12 @@ QtObject:
if(chats[i].chatType == ChatType.OneToOne and not self.contactService.getContactById(chatId).isContact): if(chats[i].chatType == ChatType.OneToOne and not self.contactService.getContactById(chatId).isContact):
continue 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] var chatMessages: seq[MessageDto]
for msg in messages: for msg in messages:
if(msg.localChatId != chatId): if(msg.localChatId != chatId):