Merge pull request #2361 from weaveworks/change-instance-fix

Clear client polling and nodes state on dismount
This commit is contained in:
Jordan Pellizzari
2017-03-22 08:37:01 -07:00
committed by GitHub
5 changed files with 62 additions and 41 deletions

View File

@@ -17,7 +17,7 @@ import {
getNodeDetails,
getTopologies,
deletePipe,
stopTopologyPolling,
stopPolling,
teardownWebsockets,
} from '../utils/web-api-utils';
import { getCurrentTopologyUrl } from '../utils/topology-utils';
@@ -720,20 +720,17 @@ export function toggleTroubleshootingMenu(ev) {
export function changeInstance() {
return (dispatch, getState) => {
dispatch({ type: ActionTypes.CHANGE_INSTANCE });
dispatch({
type: ActionTypes.CHANGE_INSTANCE
});
updateRoute(getState);
const state = getState();
getTopologies(activeTopologyOptionsSelector(state), dispatch);
getNodesDelta(
getCurrentTopologyUrl(state),
activeTopologyOptionsSelector(state),
dispatch,
true // forces websocket teardown and reconnect to new instance
);
};
}
export function shutdown() {
stopTopologyPolling();
stopPolling();
teardownWebsockets();
return {
type: ActionTypes.SHUTDOWN
};
}

View File

@@ -42,9 +42,10 @@ class App extends React.Component {
window.addEventListener('keyup', this.onKeyUp);
getRouter(this.props.dispatch, this.props.urlState).start({hashbang: true});
if (!this.props.routeSet) {
// dont request topologies when already done via router
getTopologies(this.props.activeTopologyOptions, this.props.dispatch);
if (!this.props.routeSet || process.env.WEAVE_CLOUD) {
// dont request topologies when already done via router.
// If running as a component, always request topologies when the app mounts.
getTopologies(this.props.activeTopologyOptions, this.props.dispatch, true);
}
getApiDetails(this.props.dispatch);
}
@@ -52,7 +53,7 @@ class App extends React.Component {
componentWillUnmount() {
window.removeEventListener('keypress', this.onKeyPress);
window.removeEventListener('keyup', this.onKeyUp);
shutdown();
this.props.dispatch(shutdown());
}
onKeyUp(ev) {

View File

@@ -62,6 +62,7 @@ const ACTION_TYPES = [
'SET_GRID_MODE',
'CHANGE_INSTANCE',
'TOGGLE_CONTRAST_MODE',
'SHUTDOWN'
];
export default zipObject(ACTION_TYPES, ACTION_TYPES);

View File

@@ -744,6 +744,11 @@ export function rootReducer(state = initialState, action) {
return state.set('contrastMode', action.enabled);
}
case ActionTypes.SHUTDOWN: {
state = clearNodes(state);
return state.set('nodesLoaded', false);
}
default: {
return state;
}

View File

@@ -40,6 +40,7 @@ let apiDetailsTimer = 0;
let controlErrorTimer = 0;
let createWebsocketAt = 0;
let firstMessageOnWebsocketAt = 0;
let continuePolling = true;
export function buildOptionsQuery(options) {
if (options) {
@@ -111,9 +112,11 @@ function createWebsocket(topologyUrl, optionsQuery, dispatch) {
socket = null;
dispatch(closeWebsocket());
reconnectTimer = setTimeout(() => {
createWebsocket(topologyUrl, optionsQuery, dispatch);
}, reconnectTimerInterval);
if (continuePolling) {
reconnectTimer = setTimeout(() => {
createWebsocket(topologyUrl, optionsQuery, dispatch);
}, reconnectTimerInterval);
}
};
socket.onerror = () => {
@@ -172,35 +175,44 @@ export function getAllNodes(getState, dispatch) {
Promise.resolve());
}
export function getTopologies(options, dispatch) {
export function getTopologies(options, dispatch, initialPoll) {
// Used to resume polling when navigating between pages in Weave Cloud.
continuePolling = initialPoll === true ? true : continuePolling;
clearTimeout(topologyTimer);
const optionsQuery = buildOptionsQuery(options);
const url = `${getApiPath()}/api/topology?${optionsQuery}`;
doRequest({
url,
success: (res) => {
dispatch(receiveTopologies(res));
topologyTimer = setTimeout(() => {
getTopologies(options, dispatch);
}, TOPOLOGY_INTERVAL);
if (continuePolling) {
dispatch(receiveTopologies(res));
topologyTimer = setTimeout(() => {
getTopologies(options, dispatch);
}, TOPOLOGY_INTERVAL);
}
},
error: (err) => {
log(`Error in topology request: ${err.responseText}`);
error: (req) => {
log(`Error in topology request: ${req.responseText}`);
dispatch(receiveError(url));
topologyTimer = setTimeout(() => {
getTopologies(options, dispatch);
}, TOPOLOGY_INTERVAL);
// Only retry in stand-alone mode
if (continuePolling) {
topologyTimer = setTimeout(() => {
getTopologies(options, dispatch);
}, TOPOLOGY_INTERVAL);
}
}
});
}
export function getNodesDelta(topologyUrl, options, dispatch, forceReload) {
export function getNodesDelta(topologyUrl, options, dispatch) {
const optionsQuery = buildOptionsQuery(options);
// Only recreate websocket if url changed or if forced (weave cloud instance reload);
// Check for truthy options and that options have changed.
const isNewOptions = currentOptions && currentOptions !== optionsQuery;
const isNewUrl = topologyUrl && (topologyUrl !== currentUrl || isNewOptions);
if (forceReload || isNewUrl) {
const isNewUrl = topologyUrl !== currentUrl || isNewOptions;
// `topologyUrl` can be undefined initially, so only create a socket if it is truthy
// and no socket exists, or if we get a new url.
if ((topologyUrl && !socket) || (topologyUrl && isNewUrl)) {
createWebsocket(topologyUrl, optionsQuery, dispatch);
currentUrl = topologyUrl;
currentOptions = optionsQuery;
@@ -250,16 +262,20 @@ export function getApiDetails(dispatch) {
url,
success: (res) => {
dispatch(receiveApiDetails(res));
apiDetailsTimer = setTimeout(() => {
getApiDetails(dispatch);
}, API_INTERVAL);
if (continuePolling) {
apiDetailsTimer = setTimeout(() => {
getApiDetails(dispatch);
}, API_INTERVAL);
}
},
error: (err) => {
log(`Error in api details request: ${err.responseText}`);
error: (req) => {
log(`Error in api details request: ${req.responseText}`);
receiveError(url);
apiDetailsTimer = setTimeout(() => {
getApiDetails(dispatch);
}, API_INTERVAL / 2);
if (continuePolling) {
apiDetailsTimer = setTimeout(() => {
getApiDetails(dispatch);
}, API_INTERVAL / 2);
}
}
});
}
@@ -353,9 +369,10 @@ export function getPipeStatus(pipeId, dispatch) {
});
}
export function stopTopologyPolling() {
export function stopPolling() {
clearTimeout(apiDetailsTimer);
clearTimeout(topologyTimer);
topologyTimer = 0;
continuePolling = false;
}
export function teardownWebsockets() {