From 6f7627c6cdb0de24c5e0be04c8e80d363f622b2a Mon Sep 17 00:00:00 2001
From: Mathis Neumann <mathis@simpletechs.net>
Date: Fri, 8 Jul 2016 13:47:59 +0200
Subject: [PATCH] websocket as a service

---
 app/app.js                       |  6 ++++
 app/index.html                   |  2 +-
 app/routes/deployments/single.js | 10 +++++-
 app/services/changelog-stream.js | 60 ++++++++++++++++++++++++++++++++
 4 files changed, 76 insertions(+), 2 deletions(-)
 create mode 100644 app/services/changelog-stream.js

diff --git a/app/app.js b/app/app.js
index 7839564..892f6f7 100644
--- a/app/app.js
+++ b/app/app.js
@@ -1,4 +1,5 @@
 import Ember from 'ember';
+import EmberData from 'ember-data';
 import Resolver from './resolver';
 import loadInitializers from 'ember-load-initializers';
 import config from './config/environment';
@@ -22,6 +23,11 @@ loadInitializers(App, config.modulePrefix);
 
 export default App;
 
+// TODO: just for development purposes
+window.App = App;
+window.Ember = Ember;
+window.EmberData = EmberData;
+
 // ember (via ember-runtime) sets native prototype enhancements like .property/.observer, but as enumerable
 // we need to fix enumerability since it breaks cose-bilkent and sometimes cytoscape
 function avoidEnumerableNativeExtensions(proto) {
diff --git a/app/index.html b/app/index.html
index 35d1ce4..56f96a9 100644
--- a/app/index.html
+++ b/app/index.html
@@ -3,7 +3,7 @@
   <head>
     <meta charset="utf-8">
     <meta http-equiv="X-UA-Compatible" content="IE=edge">
-    <title>FrontendPrototype</title>
+    <title>iObserve UI</title>
     <meta name="description" content="">
     <meta name="viewport" content="width=device-width, initial-scale=1">
 
diff --git a/app/routes/deployments/single.js b/app/routes/deployments/single.js
index cd7c872..7ef6e2b 100644
--- a/app/routes/deployments/single.js
+++ b/app/routes/deployments/single.js
@@ -3,8 +3,13 @@ import Ember from 'ember';
 export default Ember.Route.extend({
   session: Ember.inject.service(), // loads services/session.js
   graphingService: Ember.inject.service(),
+  changelogStream: Ember.inject.service(),
   model(params) {
-    this.set('session.systemId', params.systemId); // add the system to all requests
+    const systemId = params.systemId;
+    this.set('session.systemId', systemId); // add the system to all requests
+    const changelogStream = this.get('changelogStream'); // lazy loaded, requires session id
+    changelogStream.connect(systemId);
+
     const graphingService = this.get('graphingService');
     const createGraph = graphingService.createGraph.bind(graphingService);
 
@@ -44,6 +49,9 @@ export default Ember.Route.extend({
             entityId
         });
         this.transitionTo(url);
+    },
+    willTransition() {
+        this.get('changelogStream').disconnect();
     }
   }
 });
diff --git a/app/services/changelog-stream.js b/app/services/changelog-stream.js
new file mode 100644
index 0000000..0d97072
--- /dev/null
+++ b/app/services/changelog-stream.js
@@ -0,0 +1,60 @@
+import Ember from 'ember';
+
+export default Ember.Service.extend({
+    shouldClose: false,
+    init() {
+        this._super(...arguments);
+        this.debug('session', this.get('systemId'));
+    },
+    connect(systemId) {
+        this.set('shouldClose', false);
+
+        this.debug('setting up websocket', systemId);
+        const socket = new WebSocket(`ws://localhost:8080/v1/changelogstream/${systemId}`);
+        this.set('socket', socket);
+
+        socket.onopen = this.get('events.onOpen').bind(this);
+        socket.onerror = this.get('events.onError').bind(this);
+        socket.onmessage = this.get('events.onMessage').bind(this);
+
+        // automatically reconnect
+        socket.onclose = () => {
+            if(!this.get('shouldClose')) {
+                this.debug('connection lost, reconnecting!');
+                this.set('reconnectionTimeout', setTimeout(() => {
+                    this.connect(systemId);
+                    this.set('reconnectionTimeout', null);
+                }, 500));
+            }
+        };
+
+        // close socket connection when the user closes the window/tab or nagivates to a different website
+        window.onbeforeunload = this.get('disconnect').bind(this);
+    },
+    disconnect() {
+        this.debug('disconnect');
+        this.set('shouldClose', true);
+        this.get('socket').close();
+
+        // just in case it disconnected right before disconnect() was called.
+        clearTimeout(this.get('reconnectionTimeout'));
+    },
+    events: {
+        onError(err) {
+            this.debug('socket connection encountered an error', err);
+        },
+        onOpen() {
+            this.debug('connection established');
+        },
+        onMessage(message) {
+            const changelogJson = message.data;
+            this.debug('new changelog received', changelogJson);
+            try {
+                const changelog = JSON.parse(changelogJson);
+                this.debug('changelog converted', changelog);
+            } catch (e) {
+                console.error('could not parse changelog json', e, changelogJson);
+            }
+        }
+    }
+});
-- 
GitLab