From 2a51005a91c8dc98d45e62611a417ce7678d2b7e Mon Sep 17 00:00:00 2001
From: blavenie <benoit.lavenier@e-is.pro>
Date: Wed, 26 Oct 2016 18:47:48 +0200
Subject: [PATCH] - Refactore network code - Currency: move blockchain data
 into the second tab

---
 www/js/controllers/currency-controllers.js    |   2 +-
 www/js/controllers/help-controllers.js        |   2 +-
 www/js/services/network-services.js           | 255 ++++++++++--------
 www/templates/currency/tabs/view_network.html |  77 +++---
 .../currency/tabs/view_parameters.html        |  16 --
 5 files changed, 189 insertions(+), 163 deletions(-)

diff --git a/www/js/controllers/currency-controllers.js b/www/js/controllers/currency-controllers.js
index 5676ac627..7446a9c88 100644
--- a/www/js/controllers/currency-controllers.js
+++ b/www/js/controllers/currency-controllers.js
@@ -262,7 +262,7 @@ function CurrencyViewController($scope, $q, $translate, $timeout, BMA, UIUtils,
     .then(function(){
       // Network
       $scope.loadingPeers = true;
-      csNetwork.refreshPeers();
+      csNetwork.loadPeers();
     });
   };
 
diff --git a/www/js/controllers/help-controllers.js b/www/js/controllers/help-controllers.js
index 36b0db54d..8874353a5 100644
--- a/www/js/controllers/help-controllers.js
+++ b/www/js/controllers/help-controllers.js
@@ -340,7 +340,7 @@ function HelpTipController($scope, $rootScope, $state, $window, $ionicSideMenuDe
 
       function() {
         showNetworkViewIsNeed();
-        return $scope.showHelpTip('helptip-currency-peers', {
+        return $scope.showHelpTip('helptip-currency-blockchain', {
           bindings: {
             content: 'HELP.TIP.CURRENCY_BLOCKCHAIN',
             icon: {
diff --git a/www/js/services/network-services.js b/www/js/services/network-services.js
index f1f118565..6b529fedb 100644
--- a/www/js/services/network-services.js
+++ b/www/js/services/network-services.js
@@ -13,7 +13,6 @@ angular.module('cesium.network.services', ['ngResource', 'ngApi', 'cesium.bma.se
       data = {
         bma: null,
         peers: [],
-        newPeers: [],
         knownBlocks: [],
         knownPeers: {},
         mainBuid: null,
@@ -25,7 +24,6 @@ angular.module('cesium.network.services', ['ngResource', 'ngApi', 'cesium.bma.se
       resetData = function() {
         data.bma = null;
         data.peers = [];
-        data.newPeers = [];
         data.knownBlocks = [];
         data.knownPeers = {};
         data.mainBuid = null;
@@ -55,6 +53,125 @@ angular.module('cesium.network.services', ['ngResource', 'ngApi', 'cesium.bma.se
         return data.knownBlocks;
       },
 
+      loadPeers = function() {
+        data.knownPeers = {};
+        data.peers = [];
+        data.searchingPeersOnNetwork = true;
+        data.updatingPeers = true;
+
+        var newPeers = []
+
+        if (interval) {
+          $interval.cancel(interval);
+        }
+
+        interval = $interval(function() {
+          // not same job instance
+          if (newPeers.length) {
+            flushNewPeersAndSort(newPeers);
+          }
+          else if (data.updatingPeers && !data.searchingPeersOnNetwork) {
+            data.updatingPeers = false;
+            $interval.cancel(interval);
+            console.debug('[network] Finish : all peers found. Stopping new peers check.');
+            // The peer lookup end, we can make a clean final report
+            sortPeers();
+          }
+        }, 1000);
+
+        return data.bma.wot.member.uids()
+          .then(function(uids){
+            data.uidsByPubkeys = uids;
+            return data.bma.network.peering.peers({ leaves: true });
+          })
+          .then(function(res){
+            return $q.all(res.leaves.map(function(leaf) {
+              return data.bma.network.peering.peers({ leaf: leaf })
+                .then(function(subres){
+                  var peer = subres.leaf.value;
+                  addIfNewAndOnlinePeer(peer, newPeers);
+                });
+            }))
+              .then(function(){
+                data.searchingPeersOnNetwork = false;
+              });
+          })
+          .catch(function() {
+            data.searchingPeersOnNetwork = false;
+          });
+      },
+
+      addIfNewAndOnlinePeer = function(peer, list) {
+        list = list || data.newPeers;
+        if (!peer) return;
+        peer = new Peer(peer);
+        var server = peer.getServer();
+        if (data.knownPeers[server]) return; // already processed: exit
+        refreshPeer(peer)
+          .then(function() {
+            if (peer.online) list.push(peer);
+          });
+      },
+
+      refreshPeer = function(peer) {
+        peer.server = peer.getServer();
+        peer.dns = peer.getDns();
+        peer.blockNumber = peer.block.replace(/-.+$/, '');
+        peer.uid = data.uidsByPubkeys[peer.pubkey];
+        var node = BMA.instance(peer.getHost(), peer.getPort(), false);
+        return node.blockchain.current()
+          .then(function(block){
+            peer.currentNumber = block.number;
+            peer.online = true;
+            peer.buid = buid(block);
+            if (data.knownBlocks.indexOf(peer.buid) === -1) {
+              data.knownBlocks.push(peer.buid);
+            }
+            console.debug('[network] Peer [' + peer.server + ']    status [UP]   block [' + peer.buid.substring(0, 20) + ']');
+
+            if (csSettings.data.expertMode) {
+              // Get Version
+              return node.node.summary()
+                .then(function(res){
+                  peer.version = res && res.duniter && res.duniter.version;
+                  // Get hardship
+                  if (peer.uid) {
+                    return node.blockchain.stats.hardship({pubkey: peer.pubkey})
+                      .then(function (res) {
+                        peer.level = res && res.level;
+                        return peer;
+                      });
+                  }
+                }).catch(function() {
+                  peer.version = null; // continue
+                  peer.level = null; // continue
+                  return peer;
+                });
+            }
+            else {
+              return peer;
+            }
+          })
+          .catch(function() {
+            // node is DOWN
+            peer.online=false;
+            peer.currentNumber = null;
+            peer.buid = null;
+            peer.uid = data.uidsByPubkeys[peer.pubkey];
+            console.debug('[network] Peer [' + peer.server + '] status [DOWN]');
+            return peer;
+          });
+      },
+
+      flushNewPeersAndSort = function(newPeers) {
+        newPeers = newPeers || data.newPeers;
+        if (newPeers.length) {
+          data.peers = data.peers.concat(newPeers.splice(0));
+          console.debug('[network] New peers found: sort and add them to result...');
+          sortPeers();
+        }
+      },
+
       sortPeers = function() {
         // Count peer by current block uid
         var currents = {};
@@ -86,112 +203,10 @@ angular.module('cesium.network.services', ['ngResource', 'ngApi', 'cesium.bma.se
           score += (-1       * (peer.uid ? peer.uid.charCodeAt(0) : 999)); // alphabetical order
           return -score;
         });
+        api.data.raise.changed(data); // raise event
       },
 
-      processPeer = function(peer, refresh) {
-        if (!peer) return;
-        peer = new Peer(peer);
-        var server = peer.getServer();
-        // Test each peer only once
-        if (!refresh && data.knownPeers[server]) return;
-        var skipPushToNew = refresh && !data.knownPeers[server];
-        data.knownPeers[server] = true;
-        peer.dns = peer.getDns();
-        peer.server = server;
-        peer.blockNumber = peer.block.replace(/-.+$/, '');
-        peer.uid = data.uidsByPubkeys[peer.pubkey];
-        var node = BMA.instance(peer.getHost(), peer.getPort(), false);
-        var jobs  = [
-          node.blockchain.current()
-          .then(function(block){
-            peer.currentNumber = block.number;
-            peer.online = true;
-            peer.buid = buid(block);
-            if (data.knownBlocks.indexOf(peer.buid) === -1) {
-              data.knownBlocks.push(peer.buid);
-            }
-          })
-         ];
-        if (csSettings.data.expertMode) {
-          // Get Version
-          jobs.push(node.node.summary()
-            .then(function(res){
-              peer.version = res && res.duniter && res.duniter.version;
-            }));
-
-          // Get hardship
-          if (peer.uid) {
-            jobs.push(node.blockchain.stats.hardship({pubkey: peer.pubkey})
-              .then(function(res){
-                peer.level = res && res.level;
-              }).catch(function() {
-                peer.level = null;
-              })
-            );
-          }
-        }
-        $q.all(jobs)
-          .then(function() {
-            if (!skipPushToNew) data.newPeers.push(peer);
-            console.debug('[network] Peer [' + server + ']    status [UP]   block [' + peer.buid.substring(0, 20) + ']');
-          })
-          .catch(function(err) {
-            // node is DOWN
-            peer.online=false;
-            peer.buid = null;
-            peer.uid = data.uidsByPubkeys[peer.pubkey];
-            if (!skipPushToNew) data.newPeers.push(peer);
-            console.debug('[network] Peer [' + server + '] status [DOWN]');
-          });
-      },
-
-      refreshPeers = function() {
-        if (interval) {
-          $interval.cancel(interval);
-        }
-
-        interval = $interval(function() {
-          console.debug('[network] check if finish...');
-          if (data.newPeers.length) {
-            data.peers = data.peers.concat(data.newPeers.splice(0));
-            console.debug('[network] New peers found: sort and ad them to result...');
-            sortPeers();
-            api.data.raise.changed(data); // send event to plugins
-          } else if (data.updatingPeers && !data.searchingPeersOnNetwork) {
-            console.debug('[network] Finish : all peers found. Stopping new peers check.');
-            // The peer lookup end, we can make a clean final report
-            sortPeers();
-            data.updatingPeers = false;
-            api.data.raise.changed(data); // send event to plugins
-            $interval.cancel(interval);
-          }
-        }, 1000);
 
-        data.knownPeers = {};
-        data.peers = [];
-        data.searchingPeersOnNetwork = true;
-        data.updatingPeers = true;
-        return data.bma.wot.member.uids()
-          .then(function(uids){
-            data.uidsByPubkeys = uids;
-            return data.bma.network.peering.peers({ leaves: true });
-          })
-          .then(function(res){
-            return $q.all(res.leaves.map(function(leaf) {
-              return data.bma.network.peering.peers({ leaf: leaf })
-                .then(function(subres){
-                  var peer = subres.leaf.value;
-                  processPeer(peer);
-                });
-            }))
-              .then(function(){
-                data.searchingPeersOnNetwork = false;
-              });
-          })
-          .catch(function(err) {
-            data.searchingPeersOnNetwork = false;
-          });
-      },
 
       startListeningOnSocket = function() {
         // Listen for new block
@@ -215,16 +230,26 @@ angular.module('cesium.network.services', ['ngResource', 'ngApi', 'cesium.bma.se
         });
         // Listen for new peer
         data.bma.websocket.peer().on('peer', function(peer) {
-          $timeout(function() {
-            var promise = processPeer(peer, true);
-            if (promise) promise.then(function() {
-              if (!data.updatingPeers && data.newPeers.length) {
-                data.peers = data.peers.concat(data.newPeers.splice(0));
-                console.debug('[network] New peers found: sort and ad them to result...');
+          if (!peer || data.updatingPeers) return;
+          peer = new Peer(peer);
+          var existingPeer = _.where(data.peers, {server: peer.getServer()});
+          if (existingPeer && existingPeer.length == 1) {
+            peer = existingPeer[0];
+            existingPeer = true;
+          }
+          refreshPeer(peer).then(function() {
+            if (data.updatingPeers) return; // skip if load has been started
+
+            if (existingPeer) {
+              if (!peer.online) {
+                data.peers.splice(data.peers.indexOf(peer), 1); // remove existing peers
               }
               sortPeers();
-              api.data.raise.changed(data); // send event to plugins
-            }, 1000); // Waiting block propagation
+            }
+            else if(peer.online) {
+              data.peers.push(peer);
+              sortPeers();
+            }
           });
         });
       },
@@ -236,7 +261,7 @@ angular.module('cesium.network.services', ['ngResource', 'ngApi', 'cesium.bma.se
           console.info('[network] Starting network [' + bma.node.server + ']');
           var now = new Date();
           startListeningOnSocket(resolve, reject);
-          refreshPeers()
+          loadPeers()
             .then(function(peers){
               resolve(peers);
               console.debug('[network] Started in '+(new Date().getTime() - now.getTime())+'ms');
@@ -297,7 +322,7 @@ angular.module('cesium.network.services', ['ngResource', 'ngApi', 'cesium.bma.se
       getTrustedPeers: getTrustedPeers,
       getKnownBlocks: getKnownBlocks,
       getMainBlockUid: getMainBlockUid,
-      refreshPeers: refreshPeers,
+      loadPeers: loadPeers,
       isBusy: isBusy,
       // api extension
       api: api
diff --git a/www/templates/currency/tabs/view_network.html b/www/templates/currency/tabs/view_network.html
index c40276ece..8f8a80c93 100644
--- a/www/templates/currency/tabs/view_network.html
+++ b/www/templates/currency/tabs/view_network.html
@@ -1,36 +1,53 @@
 
     <div class="list">
 
-        <div id="helptip-currency-peers"
-             class="item item-divider item-icon-right">
-            {{'PEER.PEERS'|translate}}
-            <ion-spinner class="icon" icon="android" ng-if="loadingPeers"></ion-spinner>
-            <a class="icon ion-loop gray hidden-xs hidden-sm" ng-if="!loadingPeers" ng-click="refresh()">
-            </a>
-        </div>
+      <div class="item item-divider">
+        <span translate>CURRENCY.VIEW.BLOCKCHAIN_DIVIDER</span>
+      </div>
 
-        <a class="peer-item item item-icon-left"
-           ng-repeat="peer in peers track by peer.server"
-           id="helptip-currency-peer-{{$index}}"
-           ng-class="{ assertive: !peer.online, balanced: (peer.online && peer.hasMainConsensusBlock), energized: (peer.online && !peer.hasMainConsensusBlock)}"
-           ui-sref="app.view_peer({server: peer.server})">
-            <i class="icon ion-android-globe"></i>
-            <div class="row no-padding">
-              <div class="col no-padding">
-                <h3><i ng-class="{'ion-person': peer.uid, 'ion-key': !peer.uid}"></i> {{peer.uid || peer.pubkey.substr(0,8)}}</span> <span class="gray">{{peer.dns && ' | ' + peer.dns}}</h3>
-                <h4>{{peer.server}}</h4>
-              </div>
-              <div class="col col-10 no-padding" ng-if="settings.expertMode">
-                <h3 class="hidden-sm hidden-xs hidden-md">
-                  <span ng-if="peer.level"><i class="ion-lock-combination"></i> {{peer.level}}</span>
-                  <span ng-if="!peer.level" translate>PEER.MIRROR</span>
-                </h3>
-                <h4 class="hidden-sm hidden-xs hidden-md gray">v{{peer.version}}</h4>
-              </div>
-              <div class="col col-20 no-padding">
-                <span id="helptip-currency-peer-{{$index}}-block"
-                  class="badge" ng-class="{ 'badge-balanced': peer.hasMainConsensusBlock, 'badge-energized': peer.hasConsensusBlock }">{{peer.currentNumber}}</span>
-              </div>
+      <ion-item id="helptip-currency-blockchain"
+                class="item-icon-left">
+        <i class="icon ion-clock"></i>
+        <span translate>CURRENCY.VIEW.TIME</span>
+        <span class="item-note dark">{{medianTime | formatDate}}</span>
+      </ion-item>
+
+      <ion-item class="item-icon-left">
+        <i class="icon ion-lock-combination"></i>
+        <span translate>CURRENCY.VIEW.POW_MIN</span>
+        <span class="badge badge-stable">{{difficulty | formatInteger}}</span>
+      </ion-item>
+
+      <div id="helptip-currency-peers"
+           class="item item-divider item-icon-right">
+          {{'PEER.PEERS'|translate}}
+          <ion-spinner class="icon" icon="android" ng-if="loadingPeers"></ion-spinner>
+          <a class="icon ion-loop gray hidden-xs hidden-sm" ng-if="!loadingPeers" ng-click="refresh()">
+          </a>
+      </div>
+
+      <a class="peer-item item item-icon-left"
+         ng-repeat="peer in peers track by peer.server"
+         id="helptip-currency-peer-{{$index}}"
+         ng-class="{ assertive: !peer.online, balanced: (peer.online && peer.hasMainConsensusBlock), energized: (peer.online && !peer.hasMainConsensusBlock)}"
+         ui-sref="app.view_peer({server: peer.server})">
+          <i class="icon ion-android-globe"></i>
+          <div class="row no-padding">
+            <div class="col no-padding">
+              <h3><i ng-class="{'ion-person': peer.uid, 'ion-key': !peer.uid}"></i> {{peer.uid || peer.pubkey.substr(0,8)}}</span> <span class="gray">{{peer.dns && ' | ' + peer.dns}}</h3>
+              <h4>{{peer.server}}</h4>
+            </div>
+            <div class="col col-10 no-padding" ng-if="settings.expertMode">
+              <h3 class="hidden-sm hidden-xs hidden-md">
+                <span ng-if="peer.level"><i class="ion-lock-combination"></i> {{peer.level}}</span>
+                <span ng-if="!peer.level" translate>PEER.MIRROR</span>
+              </h3>
+              <h4 class="hidden-sm hidden-xs hidden-md gray">v{{peer.version}}</h4>
+            </div>
+            <div class="col col-20 no-padding">
+              <span id="helptip-currency-peer-{{$index}}-block"
+                class="badge" ng-class="{ 'badge-balanced': peer.hasMainConsensusBlock, 'badge-energized': peer.hasConsensusBlock }">{{peer.currentNumber}}</span>
             </div>
-        </a>
+          </div>
+      </a>
     </div>
diff --git a/www/templates/currency/tabs/view_parameters.html b/www/templates/currency/tabs/view_parameters.html
index bdd2a01c4..3d59ea175 100644
--- a/www/templates/currency/tabs/view_parameters.html
+++ b/www/templates/currency/tabs/view_parameters.html
@@ -68,22 +68,6 @@
             </label>
         </div>
 
-        <div class="item item-divider">
-            <span translate>CURRENCY.VIEW.BLOCKCHAIN_DIVIDER</span>
-        </div>
-
-        <ion-item class="item-icon-left">
-            <i class="icon ion-clock"></i>
-            <span translate>CURRENCY.VIEW.TIME</span>
-            <span class="item-note dark">{{medianTime | formatDate}}</span>
-        </ion-item>
-
-        <ion-item class="item-icon-left">
-            <i class="icon ion-lock-combination"></i>
-            <span translate>CURRENCY.VIEW.POW_MIN</span>
-            <span class="badge badge-stable">{{difficulty | formatInteger}}</span>
-        </ion-item>
-
         <div id="helptip-currency-rules"
              class="item item-divider">
             <span translate>CURRENCY.VIEW.RULES_DIVIDER</span>
-- 
GitLab