From 69f8648303d9e485f8002c84195861fb8f5a836b Mon Sep 17 00:00:00 2001 From: Markus Grigull Date: Sat, 18 Mar 2017 14:53:27 +0100 Subject: [PATCH] Detect close and restart of simulators Simulator state is requested every 5 seconds if simulator is offline --- src/containers/app.js | 107 ++++++++++++------ .../simulator-data-data-manager.js | 4 + src/data-managers/simulators-data-manager.js | 49 +++++++- src/stores/simulator-data-store.js | 7 +- src/stores/simulator-store.js | 16 ++- 5 files changed, 140 insertions(+), 43 deletions(-) diff --git a/src/containers/app.js b/src/containers/app.js index 3172cb9..be25566 100644 --- a/src/containers/app.js +++ b/src/containers/app.js @@ -21,6 +21,7 @@ import Header from '../components/header'; import Footer from '../components/footer'; import SidebarMenu from '../components/menu-sidebar'; import Home from './home'; + import '../styles/app.css'; class App extends Component { @@ -28,11 +29,44 @@ class App extends Component { return [ SimulationStore, SimulatorStore, UserStore ]; } - static calculateState() { + static calculateState(prevState) { + // get list of running simulators + var simulators = SimulatorStore.getState().filter(simulator => { + return simulator.running; + }); + + // check if running simulators changed + if (prevState != null) { + var equal = true; + + // compare each element with its old one + if (prevState.runningSimulators.length === simulators.length) { + equal = prevState.runningSimulators.every(oldSimulator => { + const simulator = simulators.find(element => { + return element._id === oldSimulator._id; + }); + + if (simulator == null) { + return false; + } + + return simulator.running === oldSimulator.running; + }); + } else { + equal = false; + } + + // replace with old array to prevent change trigger + if (equal) { + simulators = prevState.runningSimulators; + } + } + return { - simulators: SimulatorStore.getState(), simulations: SimulationStore.getState(), - currentUser: UserStore.getState().currentUser + currentUser: UserStore.getState().currentUser, + + runningSimulators: simulators }; } @@ -60,44 +94,51 @@ class App extends Component { }); } - componentDidUpdate() { - if (this.state.simulators && this.state.simulations && this.state.simulations.length > 0) { - // get list of used simulators - var simulators = []; + componentWillUpdate(nextProps, nextState) { + // open connection to each required simulator + const requiredSimulators = this.requiredSimulatorsBySimulations(); - this.state.simulations.forEach((simulation) => { - // open connection to each simulator running a simulation model - simulation.models.forEach((simulationModel) => { - // add simulator to list if not already part of - const index = simulators.findIndex((element) => { - return element.simulator === simulationModel.simulator; - }); + requiredSimulators.forEach(simulator => { + this.connectSimulator(simulator); + }); + } - if (index === -1) { - simulators.push({ simulator: simulationModel.simulator, signals: simulationModel.length }); - } else { - if (simulators[index].length < simulationModel.length) { - simulators[index].length = simulationModel.length; - } - } - }); - }); + requiredSimulatorsBySimulations() { + var simulators = []; - // open connection to each simulator - this.state.simulators.forEach((simulator) => { + this.state.simulations.forEach((simulation) => { + simulation.models.forEach((simulationModel) => { + // add simulator to list if not already part of const index = simulators.findIndex((element) => { - return element.simulator === simulator._id; + return element.simulator === simulationModel.simulator; }); - if (index !== -1) { - AppDispatcher.dispatch({ - type: 'simulatorData/open', - identifier: simulator._id, - endpoint: simulator.endpoint, - signals: simulators[index].signals - }); + if (index === -1) { + simulators.push({ simulator: simulationModel.simulator, signals: simulationModel.length }); + } else { + if (simulators[index].length < simulationModel.length) { + simulators[index].length = simulationModel.length; + } } }); + }); + + return simulators; + } + + connectSimulator(data) { + // get simulator object + const simulator = this.state.runningSimulators.find(element => { + return element._id === data.simulator; + }); + + if (simulator != null) { + AppDispatcher.dispatch({ + type: 'simulatorData/open', + identifier: simulator._id, + endpoint: simulator.endpoint, + signals: data.signals + }); } } diff --git a/src/data-managers/simulator-data-data-manager.js b/src/data-managers/simulator-data-data-manager.js index dec7f66..ad11d03 100644 --- a/src/data-managers/simulator-data-data-manager.js +++ b/src/data-managers/simulator-data-data-manager.js @@ -42,6 +42,10 @@ class SimulatorDataDataManager { type: 'simulatorData/closed', identifier: identifier }); + + // remove from list + delete this._sockets[identifier]; + this._sockets[identifier] = null; } onMessage(event, identifier) { diff --git a/src/data-managers/simulators-data-manager.js b/src/data-managers/simulators-data-manager.js index dac15e1..212942e 100644 --- a/src/data-managers/simulators-data-manager.js +++ b/src/data-managers/simulators-data-manager.js @@ -14,6 +14,8 @@ import AppDispatcher from '../app-dispatcher'; class SimulatorsDataManager extends RestDataManager { constructor() { super('simulator', '/simulators'); + + this._timers = []; } isRunning(simulator) { @@ -26,24 +28,59 @@ class SimulatorsDataManager extends RestDataManager { // send request RestAPI.get('http://' + path).then(response => { // check if simulator is running - var running = false; + simulator.running = false; response.forEach(sim => { if (sim.name === name) { - running = true; + // save properties + simulator.running = true; + //simulator.defaultTypes = sim.units; + //simulator.defaultLabels = sim.series; } }); - // report simulator running state - simulator.running = running; - AppDispatcher.dispatch({ type: 'simulators/running', simulator: simulator, - running: running + running: simulator.running }); + + // remove timer if needed + if (simulator.running) { + const index = this._timers.findIndex(timer => { + return timer.simulator === simulator._id; + }); + + if (index !== -1) { + this._timers.splice(index, 1); + } + } }).catch(error => { //console.log(error); + + simulator.running = false; + + AppDispatcher.dispatch({ + type: 'simulators/running', + simulator: simulator, + running: simulator.running + }); + + // check for existing timer + const timer = this._timers.find(element => { + return element.simulator === simulator._id; + }); + + if (timer == null) { + // add timer + var self = this; + + const timerID = setInterval(function() { + self.isRunning(simulator); + }, 5000); + + this._timers.push({ id: timerID, simulator: simulator._id }); + } }); } } diff --git a/src/stores/simulator-data-store.js b/src/stores/simulator-data-store.js index 0568dcc..0f95fa2 100644 --- a/src/stores/simulator-data-store.js +++ b/src/stores/simulator-data-store.js @@ -70,10 +70,11 @@ class SimulationDataStore extends ReduceStore { case 'simulatorData/closed': // close and delete socket if (state[action.identifier] != null) { - state[action.identifier].close(); - state[action.identifier] = null; + // delete data + //delete state[action.identifier]; + //state[action.identifier] = null; - this.__emitChange(); + //this.__emitChange(); } return state; diff --git a/src/stores/simulator-store.js b/src/stores/simulator-store.js index 98d3b1b..501d9c5 100644 --- a/src/stores/simulator-store.js +++ b/src/stores/simulator-store.js @@ -18,6 +18,7 @@ class SimulatorStore extends ArrayStore { reduce(state, action) { switch (action.type) { case 'simulators/loaded': + case 'simulators/is-running': // get simulator running state if (Array.isArray(action.data)) { action.data.forEach((simulator) => { @@ -30,9 +31,22 @@ class SimulatorStore extends ArrayStore { return super.reduce(state, action); case 'simulators/running': - // update simulator return this.updateElements(state, [ action.simulator ]); + case 'simulatorData/closed': + // get simulator + var simulator = state.find(element => { + return element._id === action.identifier; + }); + + // update running state + simulator.running = false; + + // restart requesting again + SimulatorsDataManager.isRunning(simulator); + + return this.updateElements(state, [ simulator ]); + default: return super.reduce(state, action); }