mozaik
Version:
Mozaik dashboard composition tool
169 lines (129 loc) • 4.42 kB
JavaScript
import Reflux from 'reflux';
import ConfigStore from './ConfigStore';
import ApiActions from '../actions/ApiActions';
import ConfigActions from '../actions/ConfigActions';
import ConnectionStatusActions from '../actions/ConnectionStatusActions';
import NotificationsActions from '../actions/NotificationsActions';
import ConnectionStatus from '../components/ConnectionStatus.jsx';
import {
NOTIFICATION_STATUS_SUCCESS,
NOTIFICATION_STATUS_WARNING,
NOTIFICATION_STATUS_ERROR
} from './NotificationsStore';
const NOTIFICATION_ID = 'connection.status';
const CONNECTION_RETRY_DELAY_SECONDS = 15;
const CONNECTION_MAX_RETRIES = 10;
let retryCount = 0;
let reconnections = 0;
let ws = null;
let retryTimer;
let history = [];
let buffer = [];
const clearRetryTimer = () => {
if (retryTimer) {
clearTimeout(retryTimer);
retryTimer = null;
}
};
const connectWS = (config, store) => {
ConnectionStatusActions.connecting();
NotificationsActions.update(NOTIFICATION_ID, { status: NOTIFICATION_STATUS_WARNING });
let proto = 'ws';
if (config.useWssConnection === true) {
proto = 'wss';
}
let port = window.document.location.port;
if (config.wsPort !== undefined) {
port = config.wsPort;
}
let wsUrl = `${proto}://${window.document.location.hostname}`;
if (port && port !== '') {
wsUrl = `${wsUrl}:${port}`;
}
ws = new WebSocket(wsUrl);
ws.onopen = event => {
clearRetryTimer();
retryCount = 0;
ConnectionStatusActions.connected();
NotificationsActions.update(NOTIFICATION_ID, { status: NOTIFICATION_STATUS_SUCCESS });
NotificationsActions.close(NOTIFICATION_ID, 2000);
if (reconnections > 0) {
ConfigActions.loadConfig();
history.forEach(request => { ws.send(JSON.stringify(request)); });
} else {
buffer.forEach(request => { ws.send(JSON.stringify(request)); });
buffer = [];
}
reconnections++;
};
ws.onmessage = event => {
if (event.data !== '') {
store.trigger(JSON.parse(event.data));
}
};
ws.onclose = event => {
ws = null;
clearRetryTimer();
if (retryCount === 0) {
NotificationsActions.notify({
id: NOTIFICATION_ID,
component: ConnectionStatus,
status: NOTIFICATION_STATUS_WARNING,
ttl: -1
});
} else if (retryCount === CONNECTION_MAX_RETRIES) {
ConnectionStatusActions.failed(retryCount);
NotificationsActions.update(NOTIFICATION_ID, { status: NOTIFICATION_STATUS_ERROR });
return;
}
ConnectionStatusActions.delaying(retryCount, CONNECTION_RETRY_DELAY_SECONDS);
NotificationsActions.update(NOTIFICATION_ID, { status: NOTIFICATION_STATUS_WARNING });
retryTimer = setTimeout(() => {
connectWS(config, store);
}, CONNECTION_RETRY_DELAY_SECONDS * 1000);
retryCount++;
};
};
const ApiStore = Reflux.createStore({
init() {
this.listenTo(ConfigStore, this.initWs);
},
initWs(config) {
// only connect ws if it's not already connected, when connection is lost and we succeed in re-establishing it
// we reload configuration, so without this check we'll end in an infinite loop.
if (ws === null) {
connectWS(config, this);
}
this.listenTo(ApiActions.get, this.fetch);
},
fetch(id, params = {}) {
const request = { id, params };
// keep track to use when re-connecting
history.push(request);
// if websockets not ready, add request to buffer
if (ws === null || ws.readyState !== WebSocket.OPEN) {
buffer.push(request);
return;
}
ws.send(JSON.stringify({
id: id,
params: params || {}
}));
},
getHistory() {
return history;
},
getBuffer() {
return buffer;
},
reset() {
clearRetryTimer();
history = [];
buffer = [];
if (ws !== null) {
ws.close();
ws = null;
}
}
});
export default ApiStore;