Skip to content

Commit

Permalink
MM-24781 Make GM profiles API calls to be concurrent (mattermost#5436)
Browse files Browse the repository at this point in the history
* MM-24781 Make GM profiles API calls to be concurrent

  * Add p-queue as a dependdency and keep concurrency at 4 calls

* Update actions/user_actions.jsx

Co-authored-by: Guillermo Vayá <[email protected]>

Co-authored-by: Guillermo Vayá <[email protected]>
Co-authored-by: mattermod <[email protected]>
  • Loading branch information
3 people committed May 14, 2020
1 parent 46e8e65 commit a11a5b7
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 8 deletions.
19 changes: 12 additions & 7 deletions actions/user_actions.jsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.

import PQueue from 'p-queue';
import {getChannelAndMyMember, getChannelMembersByIds} from 'mattermost-redux/actions/channels';
import {savePreferences as savePreferencesRedux} from 'mattermost-redux/actions/preferences';
import {savePreferences} from 'mattermost-redux/actions/preferences';
import {getTeamMembersByIds} from 'mattermost-redux/actions/teams';
import * as UserActions from 'mattermost-redux/actions/users';
import {Preferences as PreferencesRedux, General} from 'mattermost-redux/constants';
Expand All @@ -11,7 +12,7 @@ import {
getCurrentChannelId,
getMyChannels,
getMyChannelMember,
getChannelMembersInChannels,
getChannelMembersInChannels
} from 'mattermost-redux/selectors/entities/channels';
import {getBool} from 'mattermost-redux/selectors/entities/preferences';
import {getCurrentTeamId, getTeamMember} from 'mattermost-redux/selectors/entities/teams';
Expand All @@ -22,6 +23,7 @@ import store from 'stores/redux_store.jsx';
import * as Utils from 'utils/utils.jsx';
import {Constants, Preferences, UserStatuses} from 'utils/constants';

export const queue = new PQueue({concurrency: 4});
const dispatch = store.dispatch;
const getState = store.getState;

Expand Down Expand Up @@ -153,7 +155,7 @@ export function loadNewDMIfNeeded(channelId) {
const pref = getBool(state, Preferences.CATEGORY_DIRECT_CHANNEL_SHOW, userId, false);
if (pref === false) {
const now = Utils.getTimestamp();
savePreferencesRedux(currentUserId, [
savePreferences(currentUserId, [
{user_id: currentUserId, category: Preferences.CATEGORY_DIRECT_CHANNEL_SHOW, name: userId, value: 'true'},
{user_id: currentUserId, category: Preferences.CATEGORY_CHANNEL_OPEN_TIME, name: channelId, value: now.toString()},
])(doDispatch, doGetState);
Expand Down Expand Up @@ -181,7 +183,7 @@ export function loadNewGMIfNeeded(channelId) {
function checkPreference() {
const pref = getBool(state, Preferences.CATEGORY_GROUP_CHANNEL_SHOW, channelId, false);
if (pref === false) {
dispatch(savePreferencesRedux(currentUserId, [{user_id: currentUserId, category: Preferences.CATEGORY_GROUP_CHANNEL_SHOW, name: channelId, value: 'true'}]));
dispatch(savePreferences(currentUserId, [{user_id: currentUserId, category: Preferences.CATEGORY_GROUP_CHANNEL_SHOW, name: channelId, value: 'true'}]));
loadProfilesForGM();
}
}
Expand Down Expand Up @@ -231,6 +233,7 @@ export async function loadProfilesForGM() {

for (let i = 0; i < channels.length; i++) {
const channel = channels[i];

if (channel.type !== Constants.GM_CHANNEL) {
continue;
}
Expand All @@ -256,11 +259,13 @@ export async function loadProfilesForGM() {
});
}

await dispatch(UserActions.getProfilesInChannel(channel.id, 0, Constants.MAX_USERS_IN_GM)); //eslint-disable-line no-await-in-loop
const getProfilesAction = UserActions.getProfilesInChannel(channel.id, 0, Constants.MAX_USERS_IN_GM);
queue.add(() => dispatch(getProfilesAction));
}

await queue.onEmpty();
if (newPreferences.length > 0) {
savePreferencesRedux(currentUserId, newPreferences)(dispatch, getState);
dispatch(savePreferences(currentUserId, newPreferences));
}
}

Expand Down Expand Up @@ -302,7 +307,7 @@ export async function loadProfilesForDM() {
}

if (newPreferences.length > 0) {
savePreferencesRedux(currentUserId, newPreferences)(dispatch, getState);
savePreferences(currentUserId, newPreferences)(dispatch, getState);
}

if (profilesToLoad.length > 0) {
Expand Down
69 changes: 68 additions & 1 deletion actions/user_actions.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
import thunk from 'redux-thunk';
import configureStore from 'redux-mock-store';

import {Preferences} from 'mattermost-redux/constants';
import {Preferences, General} from 'mattermost-redux/constants';

import * as UserActions from 'actions/user_actions';
import {getState} from 'stores/redux_store';
import TestHelper from 'tests/helpers/client-test-helper';

const mockStore = configureStore([thunk]);

Expand Down Expand Up @@ -46,6 +48,13 @@ jest.mock('mattermost-redux/actions/preferences', () => {
};
});

jest.mock('stores/redux_store', () => {
return {
dispatch: jest.fn(),
getState: jest.fn(),
};
});

describe('Actions.User', () => {
const initialState = {
entities: {
Expand Down Expand Up @@ -232,4 +241,62 @@ describe('Actions.User', () => {
await testStore.dispatch(UserActions.loadProfilesForGroupChannels(mockedGroupChannels));
expect(testStore.getActions()).toEqual(expectedActions);
});

test('Should call p-queue APIs on loadProfilesForGM', async () => {
const gmChannel = {id: 'gmChannel', type: General.GM_CHANNEL, team_id: ''};
UserActions.queue.add = jest.fn().mockReturnValue(jest.fn());
UserActions.queue.onEmpty = jest.fn();

const user = TestHelper.fakeUser();

const profiles = {
[user.id]: user,
};

const channels = {
[gmChannel.id]: gmChannel,
};

const channelsInTeam = {
'': [gmChannel.id],
};

const myMembers = {
[gmChannel.id]: {},
};

const state = {
entities: {
users: {
currentUserId: 'current_user_id',
profiles,
statuses: {},
profilesInChannel: {
[gmChannel.id]: new Set(['current_user_id']),
},
},
teams: {
currentTeamId: 'team_1',
},
channels: {
channels,
channelsInTeam,
myMembers,
},
preferences: {
myPreferences: {},
},
general: {
config: {},
},
},
};

const testStore = mockStore(state);
getState.mockImplementation(testStore.getState);

await UserActions.loadProfilesForGM();
expect(UserActions.queue.onEmpty).toHaveBeenCalled();
expect(UserActions.queue.add).toHaveBeenCalled();
});
});
19 changes: 19 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"marked": "github:mattermost/marked#5a06d1af25ca48927b9efe0d9c42c01c84e7839b",
"mattermost-redux": "github:mattermost/mattermost-redux#558286afe1a0543ae874a6f2cf726d012855e7c0",
"moment-timezone": "0.5.27",
"p-queue": "^6.4.0",
"pdfjs-dist": "2.0.489",
"popmotion": "8.7.0",
"popper.js": "1.16.0",
Expand Down

0 comments on commit a11a5b7

Please sign in to comment.