From b21e98e796bcb9e2811996b3dbaa3c0da29a3ff3 Mon Sep 17 00:00:00 2001 From: enahum Date: Mon, 30 Jan 2017 11:20:14 -0300 Subject: [PATCH] Websocket re-establish connection (#190) --- app/scenes/channel/channel.js | 22 ++++++++++----------- app/scenes/channel/channel_container.js | 9 ++++++++- app/scenes/load_team/load_team.js | 7 +------ app/scenes/load_team/load_team_container.js | 5 +---- service/actions/websocket.js | 6 +++++- service/client/websocket_client.js | 16 ++++++++++++--- 6 files changed, 38 insertions(+), 27 deletions(-) diff --git a/app/scenes/channel/channel.js b/app/scenes/channel/channel.js index dfac84d13..579e33448 100644 --- a/app/scenes/channel/channel.js +++ b/app/scenes/channel/channel.js @@ -22,7 +22,9 @@ export default class Channel extends React.PureComponent { openChannelDrawer: React.PropTypes.func.isRequired, openRightMenuDrawer: React.PropTypes.func.isRequired, handlePostDraftChanged: React.PropTypes.func.isRequired, - goToChannelInfo: React.PropTypes.func.isRequired + goToChannelInfo: React.PropTypes.func.isRequired, + initWebSocket: React.PropTypes.func.isRequired, + closeWebSocket: React.PropTypes.func.isRequired }).isRequired, currentTeam: React.PropTypes.object, currentChannel: React.PropTypes.object, @@ -30,17 +32,9 @@ export default class Channel extends React.PureComponent { theme: React.PropTypes.object.isRequired }; - constructor(props) { - super(props); - - this.state = { - leftSidebarOpen: false, - rightSidebarOpen: false - }; - } - componentWillMount() { const teamId = this.props.currentTeam.id; + this.props.actions.initWebSocket(); this.loadChannels(teamId); } @@ -51,6 +45,10 @@ export default class Channel extends React.PureComponent { } } + componentWillUnmount() { + this.props.actions.closeWebSocket(); + } + loadChannels = (teamId) => { this.props.actions.loadChannelsIfNecessary(teamId).then(() => { this.props.actions.loadProfilesAndTeamMembersForDMSidebar(teamId); @@ -61,12 +59,12 @@ export default class Channel extends React.PureComponent { openChannelDrawer = () => { this.refs.postTextbox.getWrappedInstance().blur(); this.props.actions.openChannelDrawer(); - } + }; openRightMenuDrawer = () => { this.refs.postTextbox.getWrappedInstance().blur(); this.props.actions.openRightMenuDrawer(); - } + }; render() { const { diff --git a/app/scenes/channel/channel_container.js b/app/scenes/channel/channel_container.js index d2a1fd243..f47899816 100644 --- a/app/scenes/channel/channel_container.js +++ b/app/scenes/channel/channel_container.js @@ -20,6 +20,11 @@ import {getCurrentChannel} from 'service/selectors/entities/channels'; import {getTheme} from 'service/selectors/entities/preferences'; import {getCurrentTeam} from 'service/selectors/entities/teams'; +import { + init as initWebSocket, + close as closeWebSocket +} from 'service/actions/websocket'; + import Channel from './channel'; function mapStateToProps(state, ownProps) { @@ -41,7 +46,9 @@ function mapDispatchToProps(dispatch) { openChannelDrawer, openRightMenuDrawer, handlePostDraftChanged, - goToChannelInfo + goToChannelInfo, + initWebSocket, + closeWebSocket }, dispatch) }; } diff --git a/app/scenes/load_team/load_team.js b/app/scenes/load_team/load_team.js index ff4f3da98..4ff8fb898 100644 --- a/app/scenes/load_team/load_team.js +++ b/app/scenes/load_team/load_team.js @@ -15,15 +15,10 @@ export default class LoadTeam extends React.Component { currentTeam: React.PropTypes.object, actions: React.PropTypes.shape({ goToChannelView: React.PropTypes.func.isRequired, - handleTeamChange: React.PropTypes.func.isRequired, - initWebsocket: React.PropTypes.func.isRequired + handleTeamChange: React.PropTypes.func.isRequired }).isRequired }; - componentWillMount() { - this.props.actions.initWebsocket(); - } - componentDidMount() { const {currentTeam, myMembers, teams} = this.props; diff --git a/app/scenes/load_team/load_team_container.js b/app/scenes/load_team/load_team_container.js index 6c5ac5bb6..9c606b497 100644 --- a/app/scenes/load_team/load_team_container.js +++ b/app/scenes/load_team/load_team_container.js @@ -6,8 +6,6 @@ import {connect} from 'react-redux'; import {goToChannelView} from 'app/actions/views/load_team'; import {handleTeamChange} from 'app/actions/views/select_team'; - -import {init} from 'service/actions/websocket'; import {getCurrentTeam} from 'service/selectors/entities/teams'; import LoadTeam from './load_team.js'; @@ -26,8 +24,7 @@ function mapDispatchToProps(dispatch) { return { actions: bindActionCreators({ goToChannelView, - handleTeamChange, - initWebsocket: init + handleTeamChange }, dispatch) }; } diff --git a/service/actions/websocket.js b/service/actions/websocket.js index 9569047c8..c676ec29f 100644 --- a/service/actions/websocket.js +++ b/service/actions/websocket.js @@ -33,7 +33,6 @@ import {getProfilesByIds, getStatusesByIds} from 'service/actions/users'; export function init(siteUrl, token, optionalWebSocket) { return async (dispatch, getState) => { - dispatch({type: GeneralTypes.WEBSOCKET_REQUEST}, getState); const config = getState().entities.general.config; let connUrl = siteUrl || Client.getUrl(); const authToken = token || Client.getToken(); @@ -59,6 +58,7 @@ export function init(siteUrl, token, optionalWebSocket) { websocketClient.setEventCallback(handleEvent); websocketClient.setReconnectCallback(handleReconnect); websocketClient.setCloseCallback(handleClose); + websocketClient.setConnectingCallback(handleConnecting); return websocketClient.initialize(connUrl, authToken, dispatch, getState, optionalWebSocket); }; } @@ -72,6 +72,10 @@ export function close() { }; } +function handleConnecting(dispatch, getState) { + dispatch({type: GeneralTypes.WEBSOCKET_REQUEST}, getState); +} + function handleFirstConnect(dispatch, getState) { dispatch({type: GeneralTypes.WEBSOCKET_SUCCESS}, getState); } diff --git a/service/client/websocket_client.js b/service/client/websocket_client.js index ddde05bc2..c57a19793 100644 --- a/service/client/websocket_client.js +++ b/service/client/websocket_client.js @@ -11,6 +11,7 @@ class WebSocketClient { constructor() { this.conn = null; this.connectionUrl = null; + this.token = null; this.sequence = 1; this.connectFailCount = 0; this.eventCallback = null; @@ -18,6 +19,7 @@ class WebSocketClient { this.reconnectCallback = null; this.errorCallback = null; this.closeCallback = null; + this.connectingCallback = null; this.dispatch = null; this.getState = null; } @@ -46,8 +48,12 @@ class WebSocketClient { } Socket = webSocketConnector; + if (this.connectingCallback) { + this.connectingCallback(dispatch, getState); + } this.conn = new Socket(connectionUrl); this.connectionUrl = connectionUrl; + this.token = token; this.dispatch = dispatch; this.getState = getState; @@ -87,7 +93,7 @@ class WebSocketClient { // If we've failed a bunch of connections then start backing off if (this.connectFailCount > MAX_WEBSOCKET_FAILS) { - retryTime = MIN_WEBSOCKET_RETRY_TIME * this.connectFailCount * this.connectFailCount; + retryTime = MIN_WEBSOCKET_RETRY_TIME * this.connectFailCount; if (retryTime > MAX_WEBSOCKET_RETRY_TIME) { retryTime = MAX_WEBSOCKET_RETRY_TIME; } @@ -95,7 +101,7 @@ class WebSocketClient { setTimeout( () => { - this.initialize(connectionUrl, token); + this.initialize(connectionUrl, token, dispatch, getState, webSocketConnector); }, retryTime ); @@ -125,6 +131,10 @@ class WebSocketClient { }); } + setConnectingCallback(callback) { + this.connectingCallback = callback; + } + setEventCallback(callback) { this.eventCallback = callback; } @@ -167,7 +177,7 @@ class WebSocketClient { this.conn.send(JSON.stringify(msg)); } else if (!this.conn || this.conn.readyState === Socket.CLOSED) { this.conn = null; - this.initialize(); + this.initialize(this.connectionUrl, this.token, this.dispatch, this.getState); } }