[SEBA-240] Better handling of Observable subscription and triggers to prevent the GUI to freeze when multiple notifications are received

Change-Id: I22380409bdb12d6661ff3fbc911d7412776d9e24
diff --git a/package.json b/package.json
index d5aeca9..b231ad6 100644
--- a/package.json
+++ b/package.json
@@ -1,5 +1,5 @@
 {
-  "version": "1.0.3",
+  "version": "1.0.4-dev",
   "dependencies": {
     "angular": "1.6.3",
     "angular-animate": "1.6.3",
diff --git a/src/app/datasources/stores/model.store.ts b/src/app/datasources/stores/model.store.ts
index b26c262..7da92f6 100644
--- a/src/app/datasources/stores/model.store.ts
+++ b/src/app/datasources/stores/model.store.ts
@@ -41,8 +41,11 @@
     'XosDebouncer',
     'XosModeldefsCache'
   ];
+
   private _collections: any; // NOTE contains a map of {model: BehaviourSubject}
   private efficientNext: any; // NOTE debounce next
+  private _ws_subscriptions: any = {}; // NOTE contains a list of models that already subscribed to the WS obeservable
+
   constructor(
     private $log: ng.ILogService,
     private webSocket: IWSEventService,
@@ -67,26 +70,25 @@
       this._collections[modelName] = new BehaviorSubject([]); // NOTE maybe this can be created when we get response from the resource
       this.loadInitialData(modelName, apiUrl);
     }
-    // else manually trigger the next with the last know value to trigger the subscribe method of who's requesting this data
-    else {
-      this.$log.debug(`[XosModelStore] QUERY: Calling "next" on: ${modelName}`);
-      this.efficientNext(this._collections[modelName]);
-    }
 
-    // NOTE do we need to subscribe every time we query?
-    this.webSocket.list()
-      .filter((e: IWSEvent) => e.model === modelName)
-      .subscribe(
-        (event: IWSEvent) => {
-          if (event.deleted) {
-            this.storeHelpers.removeItemFromCollection(event, this._collections[modelName]);
-          }
-          else {
-            this.storeHelpers.updateCollection(event, this._collections[modelName]);
-          }
-        },
-        err => this.$log.error
-      );
+    if (!angular.isDefined(this._ws_subscriptions[modelName])) {
+      // NOTE we need to subscribe to the WS observable only once
+      const s = this.webSocket.list()
+        .filter((e: IWSEvent) => e.model === modelName)
+        .subscribe(
+          (event: IWSEvent) => {
+            this.$log.debug(`[XosModelStore] WS Event`, event);
+            if (event.deleted) {
+              this.storeHelpers.removeItemFromCollection(event, this._collections[modelName]);
+            }
+            else {
+              this.storeHelpers.updateCollection(event, this._collections[modelName]);
+            }
+          },
+          err => this.$log.error
+        );
+      this._ws_subscriptions[modelName] = s;
+    }
 
     return this._collections[modelName].asObservable();
   }
@@ -130,6 +132,7 @@
     }
 
     this.query(modelName)
+      .filter((res) => _.findIndex(res, {id: modelId}) > -1)
       .subscribe((res) => {
         const model = _.find(res, {id: modelId});
         if (model) {
diff --git a/src/app/datasources/websocket/global.ts b/src/app/datasources/websocket/global.ts
index 54c7209..372821c 100644
--- a/src/app/datasources/websocket/global.ts
+++ b/src/app/datasources/websocket/global.ts
@@ -89,6 +89,7 @@
     }
 
     public list() {
+      this.$log.debug(`[WebSocket] Active subscriptions: ${this._events.observers.length}`);
       return this._events.asObservable();
     }