From d8c10b62f46a74bb543017fb0eb7fdd61029b67b Mon Sep 17 00:00:00 2001 From: "Grigorii K. Shartsev" Date: Wed, 21 Jun 2023 21:05:37 +0200 Subject: [PATCH] perf(conversations): update only changed conversation on fetch in store Signed-off-by: Grigorii K. Shartsev --- src/store/conversationsStore.js | 32 +++++++++++++++-- src/store/conversationsStore.spec.js | 54 ++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 2 deletions(-) diff --git a/src/store/conversationsStore.js b/src/store/conversationsStore.js index 066119c4554..237575fb229 100644 --- a/src/store/conversationsStore.js +++ b/src/store/conversationsStore.js @@ -203,7 +203,7 @@ const mutations = { const actions = { /** - * Add a conversation to the store and index the displayName. + * Add a conversation to the store and index the displayName * * @param {object} context default store context; * @param {object} conversation the conversation; @@ -211,6 +211,34 @@ const actions = { addConversation(context, conversation) { context.commit('addConversation', conversation) + context.dispatch('postAddConversation', conversation) + }, + + /** + * Add conversation to the store only, if it was changed according to lastActivity and modifiedSince + * + * @param {object} context dispatch context + * @param {object} payload mutation payload + * @param {object} payload.conversation the conversation + * @param {number|0} payload.modifiedSince timestamp of last state or 0 if unknown + */ + addConversationIfChanged(context, { conversation, modifiedSince }) { + if (conversation.lastActivity >= modifiedSince) { + context.commit('addConversation', conversation) + } + + context.dispatch('postAddConversation', conversation) + }, + + /** + * Post-actions after adding a conversation: + * - Get user status from 1-1 conversations + * - Add current user to the new conversation's participants + * + * @param {object} context dispatch context + * @param {object} conversation the conversation + */ + postAddConversation(context, conversation) { if (conversation.type === CONVERSATION.TYPE.ONE_TO_ONE && conversation.status) { emit('user_status:status.updated', { status: conversation.status, @@ -649,7 +677,7 @@ const actions = { dispatch('purgeConversationsStore') } response.data.ocs.data.forEach(conversation => { - dispatch('addConversation', conversation) + dispatch('addConversationIfChanged', { conversation, modifiedSince }) }) return response } catch (error) { diff --git a/src/store/conversationsStore.spec.js b/src/store/conversationsStore.spec.js index 54a7ecde2b6..36cdcbe93db 100644 --- a/src/store/conversationsStore.spec.js +++ b/src/store/conversationsStore.spec.js @@ -77,6 +77,7 @@ describe('conversationsStore', () => { participantFlags: PARTICIPANT.CALL_FLAG.DISCONNECTED, participantType: PARTICIPANT.TYPE.USER, lastPing: 600, + lastActivity: 1672531200, // 2023-01-01T00:00:00.000Z sessionId: 'session-id-1', attendeeId: 'attendee-id-1', actorType: ATTENDEE.ACTOR_TYPE.USERS, @@ -242,10 +243,12 @@ describe('conversationsStore', () => { { token: 'one_token', attendeeId: 'attendee-id-1', + lastActivity: 1675209600, // 2023-02-01T00:00:00.000Z }, { token: 'another_token', attendeeId: 'attendee-id-2', + lastActivity: 1675209600, // 2023-02-01T00:00:00.000Z }, ] @@ -271,6 +274,57 @@ describe('conversationsStore', () => { expect(updateTalkVersionHashAction).toHaveBeenCalledWith(expect.anything(), response) }) + test('fetches all conversations and update only new without purging when modifiedSince is present', async () => { + const oldConversation1 = { + token: 'tokenOne', + attendeeId: 'attendee-id-1', + lastActivity: 1672531200, // 2023-01-01T00:00:00.000Z + } + const oldConversation2 = { + token: 'tokenTwo', + attendeeId: 'attendee-id-2', + lastActivity: 1672531200, // 2023-01-01T00:00:00.000Z + } + + // Add initial conversations + store.dispatch('addConversation', oldConversation1) + store.dispatch('addConversation', oldConversation2) + + // Fetch new conversation + // The same lastActivity, as oldConversation + const newConversation1 = { + token: 'tokenOne', + attendeeId: 'attendee-id-1', + lastActivity: 1672531200, // 2023-01-01T00:00:00.000Z + } + // Has new activity + const newConversation2 = { + token: 'tokenTwo', + attendeeId: 'attendee-id-2', + lastActivity: 1675209600, // 2023-02-01T00:00:00.000Z + } + const modifiedSince = 1675209600 // 2023-02-01T00:00:00.000Z + + const response = { + data: { + ocs: { + data: [newConversation1, newConversation2], + }, + }, + } + + fetchConversations.mockResolvedValue(response) + + await store.dispatch('fetchConversations', { modifiedSince }) + + expect(fetchConversations).toHaveBeenCalledWith({ params: { modifiedSince } }) + // conversationsList is actual to the response + expect(store.getters.conversationsList).toEqual([newConversation1, newConversation2]) + // Only old conversation with new activity should be actually replaced with new objects + expect(store.state.conversationsStore.conversations[oldConversation1.token]).toStrictEqual(oldConversation1) + expect(store.state.conversationsStore.conversations[oldConversation2.token]).toStrictEqual(newConversation2) + }) + test('fetch conversation failure checks for maintenance mode', async () => { const response = { status: 503 } fetchConversation.mockRejectedValue({ response })