Skip to content
Snippets Groups Projects
Commit f4826928 authored by Mathis Neumann's avatar Mathis Neumann
Browse files

avoid buggy and unnecessary disconnects from changelog stream when switch...

avoid buggy and unnecessary disconnects from changelog stream when switch between deployments and architectures
parent aba4a6aa
No related branches found
No related tags found
No related merge requests found
...@@ -60,7 +60,8 @@ export default Route.extend({ ...@@ -60,7 +60,8 @@ export default Route.extend({
.catch(err => { .catch(err => {
if(err === 'outdated') { if(err === 'outdated') {
// wait a bit to avoid DDOS, TODO: exponential backoff? // wait a bit to avoid DDOS, TODO: exponential backoff?
this.refresh(); this.debug('data is outdated, refreshing data');
setTimeout(this.refresh.bind(this)); // refresh asynchronously to avoid infinite recursions
} else { } else {
console.error('could not load models', err); console.error('could not load models', err);
} }
...@@ -143,7 +144,7 @@ export default Route.extend({ ...@@ -143,7 +144,7 @@ export default Route.extend({
return models; return models;
}, },
actions: { actions: {
error: function(reason, transition) { error: function() {
this.debug('error', ...arguments); this.debug('error', ...arguments);
this.transitionTo('deployments'); this.transitionTo('deployments');
this.get('flashMessages').danger(`Could not find system with id "${this.get('systemId')}"`); this.get('flashMessages').danger(`Could not find system with id "${this.get('systemId')}"`);
...@@ -168,11 +169,22 @@ export default Route.extend({ ...@@ -168,11 +169,22 @@ export default Route.extend({
this.replaceWith(this.get('routeName')); this.replaceWith(this.get('routeName'));
}, },
willTransition(transition) { willTransition(transition) {
this.debug('transition', transition.targetName, this.get('routeName')); const currentRoute = this.get('routeName');
// do not disconnect if transitioning to a child route (details) const allowedRoutes = [ // support route aliases
if (transition.targetName.indexOf(this.get('routeName')) !== 0) { currentRoute.replace(/^deployments/, 'architectures'),
currentRoute.replace(/^architectures/, 'deployments')
];
const target = transition.targetName;
const keepSocketConnection = target.indexOf(allowedRoutes[0]) === 0 || target.indexOf(allowedRoutes[1]) === 0;
this.debug('transition', transition.targetName, currentRoute, allowedRoutes);
// do not disconnect if transitioning to a child route (details) or alias
if (!keepSocketConnection) {
this.debug('disconnecting from changelogStream: leaving .single route');
this.get('changelogStream').disconnect(); this.get('changelogStream').disconnect();
clearTimeout(this.get('refreshTimeout')); } else {
this.debug('keeping changelogStream connection open: navigating to subpage or alias');
} }
} }
} }
......
import Ember from 'ember'; import Ember from 'ember';
import ENV from 'iobserve-ui/config/environment'; import ENV from 'iobserve-ui/config/environment';
export default Ember.Service.extend({ const { Service, inject, RSVP } = Ember;
changelogQueue: Ember.inject.service(),
export default Service.extend({
changelogQueue: inject.service(),
init() { init() {
this._super(...arguments); this._super(...arguments);
this.debug('session', this.get('systemId')); this.debug('session', this.get('systemId'));
}, },
connect(systemId) { connect(systemId) {
return new RSVP.Promise((resolve, reject) => {
const oldSocket = this.get('socket'); const oldSocket = this.get('socket');
if(oldSocket) { if(oldSocket) {
if(this.get('systemId') === systemId) {
this.debug('already connected to the current system, doing nothing');
return;
}
this.debug('already connected, disconnecting first'); this.debug('already connected, disconnecting first');
this.disconnect(); this.disconnect();
} }
...@@ -17,9 +24,16 @@ export default Ember.Service.extend({ ...@@ -17,9 +24,16 @@ export default Ember.Service.extend({
this.debug('setting up websocket', systemId); this.debug('setting up websocket', systemId);
const socket = new WebSocket(`${ENV.APP.WEBSOCKET_ROOT}/v1/changelogstream/${systemId}`); const socket = new WebSocket(`${ENV.APP.WEBSOCKET_ROOT}/v1/changelogstream/${systemId}`);
this.set('socket', socket); this.set('socket', socket);
this.set('systemId', systemId);
socket.onopen = this.get('events.onOpen').bind(this); socket.onopen = () => {
socket.onerror = this.get('events.onError').bind(this); resolve();
return this.events.onOpen.call(this);
};
socket.onerror = () => {
reject();
return this.events.onError.call(this);
};
socket.onmessage = this.get('events.onMessage').bind(this); socket.onmessage = this.get('events.onMessage').bind(this);
// automatically reconnect // automatically reconnect
...@@ -35,6 +49,7 @@ export default Ember.Service.extend({ ...@@ -35,6 +49,7 @@ export default Ember.Service.extend({
// close socket connection when the user closes the window/tab or nagivates to a different website // close socket connection when the user closes the window/tab or nagivates to a different website
window.onbeforeunload = this.get('disconnect').bind(this); window.onbeforeunload = this.get('disconnect').bind(this);
});
}, },
disconnect() { disconnect() {
this.get('changelogQueue').reset(); this.get('changelogQueue').reset();
...@@ -45,7 +60,12 @@ export default Ember.Service.extend({ ...@@ -45,7 +60,12 @@ export default Ember.Service.extend({
this.set('socket.onopen', null); this.set('socket.onopen', null);
this.set('socket.onmessage', null); this.set('socket.onmessage', null);
try{
this.get('socket').close(); this.get('socket').close();
} catch(e) {
// probably because connection was not yet established
console.error('could not close connection', e);
}
this.set('socket', null); this.set('socket', null);
// just in case it disconnected right before disconnect() was called. // just in case it disconnected right before disconnect() was called.
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment