diff --git a/webapp/channels/src/actions/views/channel.ts b/webapp/channels/src/actions/views/channel.ts index 48409e3d39..cbbe2e9949 100644 --- a/webapp/channels/src/actions/views/channel.ts +++ b/webapp/channels/src/actions/views/channel.ts @@ -423,6 +423,8 @@ export function syncPostsInChannel(channelId: string, since: number, prefetch = sinceTimeToGetPosts = lastPostsApiCallForChannel; } + console.log('sinceTimeToGetPosts', channelId, sinceTimeToGetPosts, 'prefetch', prefetch); + if (prefetch) { dispatch({ type: ActionTypes.PREFETCH_POSTS_FOR_CHANNEL, @@ -448,6 +450,7 @@ export function syncPostsInChannel(channelId: string, since: number, prefetch = status: RequestStatus.FAILURE, }); } else { + console.log('PREFETCH_POSTS_FOR_CHANNEL', channelId, 'RequestStatus.SUCCESS', Date.now()); actions.push({ type: ActionTypes.PREFETCH_POSTS_FOR_CHANNEL, channelId, diff --git a/webapp/channels/src/actions/websocket_actions.jsx b/webapp/channels/src/actions/websocket_actions.jsx index 59677a8e8f..e49b89f974 100644 --- a/webapp/channels/src/actions/websocket_actions.jsx +++ b/webapp/channels/src/actions/websocket_actions.jsx @@ -243,6 +243,13 @@ function restart() { dispatch(getClientConfig()); } +export function reconnectWsChannels() { + console.log('[websocket_actions] reconnectWsChannels - WebSocketClient.reconnecting', WebSocketClient.reconnecting); + if (WebSocketClient.reconnecting) { + WebSocketClient.reconnectAllChannels(); + } +} + export async function reconnect(socketId) { // eslint-disable-next-line console.log('Reconnecting WebSocket'); @@ -338,7 +345,6 @@ export async function reconnect(socketId) { // eslint-disable-next-line no-console dispatch(checkForModifiedUsers(true)); dispatch(TeamActions.getMyKSuites()); - console.log('[websocket_actions] lastDisconnectAt: ', state.websocket.lastDisconnectAt); } dispatch(resetWsErrorCount()); diff --git a/webapp/channels/src/components/data_prefetch/data_prefetch.tsx b/webapp/channels/src/components/data_prefetch/data_prefetch.tsx index 90134b8156..dc13c03432 100644 --- a/webapp/channels/src/components/data_prefetch/data_prefetch.tsx +++ b/webapp/channels/src/components/data_prefetch/data_prefetch.tsx @@ -9,6 +9,7 @@ import type {Channel} from '@mattermost/types/channels'; import type {ActionResult} from 'mattermost-redux/types/actions'; import {loadProfilesForSidebar} from 'actions/user_actions'; +import {reconnectWsChannels} from 'actions/websocket_actions'; import {Constants} from 'utils/constants'; @@ -54,7 +55,7 @@ export default class DataPrefetch extends React.PureComponent { private prefetchTimeout?: number; async componentDidUpdate(prevProps: Props) { - const {currentChannelId, prefetchQueueObj, sidebarLoaded} = this.props; + const {currentChannelId, prefetchQueueObj, sidebarLoaded, prefetchRequestStatus} = this.props; if (currentChannelId && sidebarLoaded && (!prevProps.currentChannelId || !prevProps.sidebarLoaded)) { queue.add(async () => this.prefetchPosts(currentChannelId)); await loadProfilesForSidebar(); @@ -65,6 +66,20 @@ export default class DataPrefetch extends React.PureComponent { this.prefetchData(); } + // console.log('prefetchQueueObj', prefetchQueueObj); + + // Infomaniak: if websocket is connecting at the same time this will delay channel subscriptions until all channels have finished prefetch + if (prevProps.prefetchQueueObj !== prefetchQueueObj || prevProps.prefetchRequestStatus !== prefetchRequestStatus) { + const queueCount = Object.values(prefetchQueueObj).map((x) => x.length).reduce((accumulator, currentValue) => accumulator + currentValue, 0); + const statusCount = Object.keys(prefetchRequestStatus).length; + const allStatusSuccessful = !(Object.values(prefetchRequestStatus).some((x) => x !== 'success')); + + if (queueCount === statusCount && allStatusSuccessful) { + console.log('prefetch complete'); + reconnectWsChannels(); + } + } + if (currentChannelId && sidebarLoaded && (!prevProps.currentChannelId || !prevProps.sidebarLoaded)) { this.props.actions.trackPreloadedChannels(prefetchQueueObj); } diff --git a/webapp/channels/src/components/post_view/post_body_additional_content/__snapshots__/post_body_additional_content.test.tsx.snap b/webapp/channels/src/components/post_view/post_body_additional_content/__snapshots__/post_body_additional_content.test.tsx.snap index d5e38c9159..42c85b6599 100644 --- a/webapp/channels/src/components/post_view/post_body_additional_content/__snapshots__/post_body_additional_content.test.tsx.snap +++ b/webapp/channels/src/components/post_view/post_body_additional_content/__snapshots__/post_body_additional_content.test.tsx.snap @@ -97,6 +97,12 @@ exports[`PostBodyAdditionalContent with a normal link Should render the plugin c } webSocketClient={ WebSocketClient { + "_currentUserId": undefined, + "_currentUserTeamId": undefined, + "_presenceChannelId": undefined, + "_teamId": undefined, + "_userId": undefined, + "_userTeamId": undefined, "closeCallback": null, "closeListeners": Set {}, "conn": null, @@ -122,6 +128,7 @@ exports[`PostBodyAdditionalContent with a normal link Should render the plugin c "presenceChannel": null, "reconnectCallback": null, "reconnectListeners": Set {}, + "reconnecting": false, "responseCallbacks": Object {}, "responseSequence": 1, "serverSequence": 0, @@ -156,6 +163,12 @@ exports[`PostBodyAdditionalContent with a normal link Should render the plugin c } webSocketClient={ WebSocketClient { + "_currentUserId": undefined, + "_currentUserTeamId": undefined, + "_presenceChannelId": undefined, + "_teamId": undefined, + "_userId": undefined, + "_userTeamId": undefined, "closeCallback": null, "closeListeners": Set {}, "conn": null, @@ -181,6 +194,7 @@ exports[`PostBodyAdditionalContent with a normal link Should render the plugin c "presenceChannel": null, "reconnectCallback": null, "reconnectListeners": Set {}, + "reconnecting": false, "responseCallbacks": Object {}, "responseSequence": 1, "serverSequence": 0, diff --git a/webapp/channels/src/plugins/pluggable/__snapshots__/pluggable.test.tsx.snap b/webapp/channels/src/plugins/pluggable/__snapshots__/pluggable.test.tsx.snap index b49b96f31f..771d117a0b 100644 --- a/webapp/channels/src/plugins/pluggable/__snapshots__/pluggable.test.tsx.snap +++ b/webapp/channels/src/plugins/pluggable/__snapshots__/pluggable.test.tsx.snap @@ -41,6 +41,12 @@ exports[`plugins/Pluggable should match snapshot with extended component 1`] = ` { - this.subscribeToTeamChannel(teamId as string); - this.subscribeToUserChannel(userId || currentUserId); - this.subscribeToUserTeamScopedChannel(userTeamId || currentUserTeamId); - this.subscribeToOtherTeams(this.otherTeams, teamId) - - // There is a case where presenceChannelId can be undefined on first connect and will be set by the bind function later. - const presenceChannel = presenceChannelId || this.currentPresence; - if (presenceChannel) { - this.bindPresenceChannel(presenceChannel); - } + console.log('[websocket] socketId', this.conn?.connection.socket_id); + + // TODO: temp bind just to keep consistence with old code + this._teamId = teamId; + this._userId = userId; + this._currentUserId = currentUserId; + this._userTeamId = userTeamId; + this._currentUserTeamId = currentUserTeamId; + this._presenceChannelId = presenceChannelId; - console.log('[websocket] re-established connection'); if (this.connectFailCount > 0) { console.log('[websocket] calling reconnect callbacks'); - console.log('[websocket] socketId', this.conn?.connection.socket_id); + // used by websocket_actions to determine whether to call reconnectAllChannels after preload + this.reconnecting = true; + console.log('[websocket] reconnecting'); this.reconnectCallback?.(this.conn?.connection.socket_id); this.reconnectListeners.forEach((listener) => listener(this.conn?.connection.socket_id)); } else if (this.firstConnectCallback || this.firstConnectListeners.size > 0) { + // if first connect manually call reconnectAllChannels + this.reconnectAllChannels(); console.log('[websocket] calling first connect callbacks'); - console.log('[websocket] socketId', this.conn?.connection.socket_id); this.firstConnectCallback?.(this.conn?.connection.socket_id); this.firstConnectListeners.forEach((listener) => listener(this.conn?.connection.socket_id)); } + this.connectFailCount = 0; this.errorCount = 0; this.socketId = this.conn?.connection.socket_id as string; }); } + reconnectAllChannels() { + console.log('[websocket] reconnectAllChannels state', this.conn?.connection.state) + if (this.conn?.connection.state !== 'connected') { + console.log('[websocket] reconnectAllChannels retrying'); + setTimeout(() => { + this.reconnectAllChannels(); + }, 2000); + + return; + } + this.subscribeToTeamChannel(this._teamId as string); + this.subscribeToUserChannel(this._userId || this._currentUserId); + this.subscribeToUserTeamScopedChannel(this._userTeamId || this._currentUserTeamId); + this.subscribeToOtherTeams(this.otherTeams, this._teamId); + + const presenceChannel = this._presenceChannelId || this.currentPresence; + if (presenceChannel) { + this.bindPresenceChannel(presenceChannel); + } + + this.reconnecting = false; + console.log('[websocket] connected at', Date.now()); + } + updateToken(token: string) { if (this.conn) { this.conn.disconnect();