perf(ChatLoadingTime): Separate get chat messages and get pinned messages in different tasks

This commit is contained in:
Alex Jbanca 2023-04-12 12:50:42 +03:00 committed by Alex Jbanca
parent d5e5ba2796
commit d1ffa2e3b3
6 changed files with 105 additions and 49 deletions

View File

@ -58,8 +58,8 @@ proc delete*(self: Controller) =
self.events.disconnect()
proc init*(self: Controller) =
self.events.on(SIGNAL_MESSAGES_LOADED) do(e:Args):
let args = MessagesLoadedArgs(e)
self.events.on(SIGNAL_PINNED_MESSAGES_LOADED) do(e:Args):
let args = PinnedMessagesLoadedArgs(e)
if(self.chatId != args.chatId or args.pinnedMessages.len == 0):
return
self.delegate.newPinnedMessagesLoaded(args.pinnedMessages)

View File

@ -58,7 +58,13 @@ proc init*(self: Controller) =
let args = MessagesLoadedArgs(e)
if(self.chatId != args.chatId):
return
self.delegate.newMessagesLoaded(args.messages, args.reactions, args.pinnedMessages)
self.delegate.newMessagesLoaded(args.messages, args.reactions)
self.events.on(SIGNAL_PINNED_MESSAGES_LOADED) do(e:Args):
let args = PinnedMessagesLoadedArgs(e)
if(self.chatId != args.chatId):
return
self.delegate.newPinnedMessagesLoaded(args.pinnedMessages)
self.events.on(SIGNAL_NEW_MESSAGE_RECEIVED) do(e: Args):
var args = MessagesArgs(e)

View File

@ -25,8 +25,10 @@ method updateChatIdentifier*(self: AccessInterface) {.base.} =
method updateChatFetchMoreMessages*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method newMessagesLoaded*(self: AccessInterface, messages: seq[MessageDto], reactions: seq[ReactionDto],
pinnedMessages: seq[PinnedMessageDto]) {.base.} =
method newMessagesLoaded*(self: AccessInterface, messages: seq[MessageDto], reactions: seq[ReactionDto]) {.base.} =
raise newException(ValueError, "No implementation available")
method newPinnedMessagesLoaded*(self: AccessInterface, pinnedMessages: seq[PinnedMessageDto]) {.base.} =
raise newException(ValueError, "No implementation available")
method onReactionAdded*(self: AccessInterface, messageId: string, emojiId: int, reactionId: string) {.base.} =

View File

@ -221,8 +221,7 @@ method reevaluateViewLoadingState*(self: Module) =
not self.firstUnseenMessageState.initialized or
self.firstUnseenMessageState.fetching)
method newMessagesLoaded*(self: Module, messages: seq[MessageDto], reactions: seq[ReactionDto],
pinnedMessages: seq[PinnedMessageDto]) =
method newMessagesLoaded*(self: Module, messages: seq[MessageDto], reactions: seq[ReactionDto]) =
var viewItems: seq[Item]
if(messages.len > 0):
@ -327,11 +326,6 @@ method newMessagesLoaded*(self: Module, messages: seq[MessageDto], reactions: se
else:
error "wrong emoji id found when loading messages", methodName="newMessagesLoaded"
for p in pinnedMessages:
if(p.message.id == message.id):
item.pinned = true
item.pinnedBy = p.pinnedBy
if message.editedAt != 0:
item.isEdited = true
@ -357,6 +351,10 @@ method newMessagesLoaded*(self: Module, messages: seq[MessageDto], reactions: se
self.initialMessagesLoaded = true
self.reevaluateViewLoadingState()
method newPinnedMessagesLoaded*(self: Module, pinnedMessages: seq[PinnedMessageDto]) =
for p in pinnedMessages:
self.onPinMessage(p.message.id, p.pinnedBy)
method messagesAdded*(self: Module, messages: seq[MessageDto]) =
var items: seq[Item]

View File

@ -12,7 +12,6 @@ type
AsyncFetchChatMessagesTaskArg = ref object of QObjectTaskArg
chatId: string
msgCursor: string
pinnedMsgCursor: string
limit: int
const asyncFetchChatMessagesTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
@ -32,16 +31,6 @@ const asyncFetchChatMessagesTask: Task = proc(argEncoded: string) {.gcsafe, nimc
responseJson["messages"] = messagesArr
responseJson["messagesCursor"] = messagesCursor
# handle pinned messages
if(arg.pinnedMsgCursor != CURSOR_VALUE_IGNORE):
var pinnedMsgArr: JsonNode
var pinnedMsgCursor: JsonNode
let pinnedMsgsResponse = status_go.fetchPinnedMessages(arg.chatId, arg.pinnedMsgCursor, arg.limit)
discard pinnedMsgsResponse.result.getProp("cursor", pinnedMsgCursor)
discard pinnedMsgsResponse.result.getProp("pinnedMessages", pinnedMsgArr)
responseJson["pinnedMessages"] = pinnedMsgArr
responseJson["pinnedMessagesCursor"] = pinnedMsgCursor
# handle reactions
if(arg.msgCursor != CURSOR_VALUE_IGNORE):
# messages and reactions are using the same cursor
@ -52,6 +41,28 @@ const asyncFetchChatMessagesTask: Task = proc(argEncoded: string) {.gcsafe, nimc
arg.finish(responseJson)
#################################################
# Async load pinned messages
#################################################
const asyncFetchPinnedChatMessagesTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
let arg = decode[AsyncFetchChatMessagesTaskArg](argEncoded)
var responseJson = %*{
"chatId": arg.chatId
}
#handle pinned messages
if(arg.msgCursor != CURSOR_VALUE_IGNORE):
var pinnedMsgArr: JsonNode
var msgCursor: JsonNode
let pinnedMsgsResponse = status_go.fetchPinnedMessages(arg.chatId, arg.msgCursor, arg.limit)
discard pinnedMsgsResponse.result.getProp("cursor", msgCursor)
discard pinnedMsgsResponse.result.getProp("pinnedMessages", pinnedMsgArr)
responseJson["pinnedMessages"] = pinnedMsgArr
responseJson["pinnedMessagesCursor"] = msgCursor
arg.finish(responseJson)
#################################################
# Async search messages
#################################################

View File

@ -40,6 +40,7 @@ const WEEK_AS_MILLISECONDS = initDuration(seconds = 60*60*24*7).inMilliSeconds
# Signals which may be emitted by this service:
const SIGNAL_MESSAGES_LOADED* = "messagesLoaded"
const SIGNAL_PINNED_MESSAGES_LOADED* = "pinnedMessagesLoaded"
const SIGNAL_FIRST_UNSEEN_MESSAGE_LOADED* = "firstUnseenMessageLoaded"
const SIGNAL_NEW_MESSAGE_RECEIVED* = "newMessageReceived"
const SIGNAL_MESSAGE_PINNED* = "messagePinned"
@ -72,9 +73,12 @@ type
MessagesLoadedArgs* = ref object of Args
chatId*: string
messages*: seq[MessageDto]
pinnedMessages*: seq[PinnedMessageDto]
reactions*: seq[ReactionDto]
PinnedMessagesLoadedArgs* = ref object of Args
chatId*: string
pinnedMessages*: seq[PinnedMessageDto]
MessagePinUnpinArgs* = ref object of Args
chatId*: string
messageId*: string
@ -188,16 +192,11 @@ QtObject:
let msgCursor = self.initOrGetMessageCursor(chatId)
let msgCursorValue = if (msgCursor.isFetchable()): msgCursor.getValue() else: CURSOR_VALUE_IGNORE
let pinnedMsgCursor = self.initOrGetPinnedMessageCursor(chatId)
let pinnedMsgCursorValue = if (pinnedMsgCursor.isFetchable()): pinnedMsgCursor.getValue() else: CURSOR_VALUE_IGNORE
if(msgCursorValue == CURSOR_VALUE_IGNORE and pinnedMsgCursorValue == CURSOR_VALUE_IGNORE):
if(msgCursorValue == CURSOR_VALUE_IGNORE):
return
if(msgCursorValue != CURSOR_VALUE_IGNORE):
msgCursor.setPending()
if (pinnedMsgCursorValue != CURSOR_VALUE_IGNORE):
pinnedMsgCursor.setPending()
let arg = AsyncFetchChatMessagesTaskArg(
tptr: cast[ByteAddress](asyncFetchChatMessagesTask),
@ -205,17 +204,39 @@ QtObject:
slot: "onAsyncLoadMoreMessagesForChat",
chatId: chatId,
msgCursor: msgCursorValue,
pinnedMsgCursor: pinnedMsgCursorValue,
limit: if(limit <= MESSAGES_PER_PAGE_MAX): limit else: MESSAGES_PER_PAGE_MAX
)
self.threadpool.start(arg)
proc asyncLoadPinnedMessagesForChat*(self: Service, chatId: string) =
if (chatId.len == 0):
error "empty chat id", procName="asyncLoadPinnedMessagesForChat"
return
let pinnedMsgCursor = self.initOrGetPinnedMessageCursor(chatId)
let pinnedMsgCursorValue = if (pinnedMsgCursor.isFetchable()): pinnedMsgCursor.getValue() else: CURSOR_VALUE_IGNORE
if(pinnedMsgCursorValue == CURSOR_VALUE_IGNORE):
return
pinnedMsgCursor.setPending()
let arg = AsyncFetchChatMessagesTaskArg(
tptr: cast[ByteAddress](asyncFetchPinnedChatMessagesTask),
vptr: cast[ByteAddress](self.vptr),
slot: "onAsyncLoadPinnedMessagesForChat",
chatId: chatId,
msgCursor: pinnedMsgCursorValue,
limit: MESSAGES_PER_PAGE_MAX
)
self.threadpool.start(arg)
proc asyncLoadInitialMessagesForChat*(self: Service, chatId: string) =
if(self.isChatCursorInitialized(chatId)):
let data = MessagesLoadedArgs(chatId: chatId,
messages: @[],
pinnedMessages: @[],
reactions: @[])
self.events.emit(SIGNAL_MESSAGES_LOADED, data)
@ -389,30 +410,17 @@ QtObject:
weiStr.trimZeros()
return (tokenStr, weiStr)
proc onAsyncLoadMoreMessagesForChat*(self: Service, response: string) {.slot.} =
proc onAsyncLoadPinnedMessagesForChat*(self: Service, response: string) {.slot.} =
let responseObj = response.parseJson
if (responseObj.kind != JObject):
info "load more messages response is not a json object"
# notify view, this is important
self.events.emit(SIGNAL_MESSAGES_LOADED, MessagesLoadedArgs())
info "load pinned messages response is not a json object"
self.events.emit(SIGNAL_PINNED_MESSAGES_LOADED, PinnedMessagesLoadedArgs())
return
var chatId: string
discard responseObj.getProp("chatId", chatId)
let msgCursor = self.initOrGetMessageCursor(chatId)
let pinnedMsgCursor = self.initOrGetPinnedMessageCursor(chatId)
# handling messages
var msgCursorValue: string
if(responseObj.getProp("messagesCursor", msgCursorValue)):
msgCursor.setValue(msgCursorValue)
var messagesArr: JsonNode
var messages: seq[MessageDto]
if(responseObj.getProp("messages", messagesArr)):
messages = map(messagesArr.getElems(), proc(x: JsonNode): MessageDto = x.toMessageDto())
# handling pinned messages
var pinnedMsgCursorValue: string
if(responseObj.getProp("pinnedMessagesCursor", pinnedMsgCursorValue)):
@ -426,6 +434,38 @@ QtObject:
# set initial number of pinned messages
self.numOfPinnedMessagesPerChat[chatId] = pinnedMessages.len
let data = PinnedMessagesLoadedArgs(chatId: chatId,
pinnedMessages: pinnedMessages)
self.events.emit(SIGNAL_PINNED_MESSAGES_LOADED, data)
proc onAsyncLoadMoreMessagesForChat*(self: Service, response: string) {.slot.} =
let responseObj = response.parseJson
if (responseObj.kind != JObject):
info "load more messages response is not a json object"
# notify view, this is important
self.events.emit(SIGNAL_MESSAGES_LOADED, MessagesLoadedArgs())
return
var chatId: string
discard responseObj.getProp("chatId", chatId)
let msgCursor = self.initOrGetMessageCursor(chatId)
if(msgCursor.getValue() == ""):
# this is the first time we load messages for this chat
# we need to load pinned messages as well
self.asyncLoadPinnedMessagesForChat(chatId)
# handling messages
var msgCursorValue: string
if(responseObj.getProp("messagesCursor", msgCursorValue)):
msgCursor.setValue(msgCursorValue)
var messagesArr: JsonNode
var messages: seq[MessageDto]
if(responseObj.getProp("messages", messagesArr)):
messages = map(messagesArr.getElems(), proc(x: JsonNode): MessageDto = x.toMessageDto())
# handling reactions
var reactionsArr: JsonNode
var reactions: seq[ReactionDto]
@ -434,7 +474,6 @@ QtObject:
let data = MessagesLoadedArgs(chatId: chatId,
messages: messages,
pinnedMessages: pinnedMessages,
reactions: reactions)
self.events.emit(SIGNAL_MESSAGES_LOADED, data)