From 10d605e1f12b7c77852dda3141da1a918cc81f24 Mon Sep 17 00:00:00 2001
From: jsalyers <jsalyers@syncad.com>
Date: Thu, 9 Apr 2020 18:30:31 -0400
Subject: [PATCH] [JES] Add automatic failover capability

---
 config.json                |  8 ++---
 package.json               |  6 ++--
 src/api/index.js           | 66 +++++++++++++++++++-------------------
 src/api/transports/http.js |  1 -
 src/config.js              | 24 --------------
 5 files changed, 40 insertions(+), 65 deletions(-)
 delete mode 100644 src/config.js

diff --git a/config.json b/config.json
index 3a5eb45..e4da8c5 100644
--- a/config.json
+++ b/config.json
@@ -1,10 +1,10 @@
 {
   "transport": "http",
   "websocket": "wss://api.hive.blog:8090",
-  "uri": "https://anyx.io",
-  "url": "https://anyx.io",
-  "dev_uri": "https://api.steemitdev.com",
-  "stage_uri": "https://api.steemitstage.com",
+  "uri": "https://api.hive.blog",
+  "url": "https://api.hive.blog",
+  "dev_uri": "",
+  "stage_uri": "",
   "address_prefix": "STM",
   "chain_id": "0000000000000000000000000000000000000000000000000000000000000000",
   "alternative_api_endpoints": ["https://api.hive.blog", "https://anyx.io"],
diff --git a/package.json b/package.json
index da8a724..95b7bed 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
-  "name": "hive-js-dev",
-  "version": "0.0.9",
-  "description": "Steem.js the JavaScript API for Steem blockchain",
+  "name": "@hiveio/hive-js",
+  "version": "0.0.2",
+  "description": "Hive.js the JavaScript API for Hive blockchain",
   "main": "lib/index.js",
   "scripts": {
     "test": "eslint --quiet src test; mocha -t 40000 --require babel-polyfill --require babel-register",
diff --git a/src/api/index.js b/src/api/index.js
index 26d7dd7..05d7e4f 100644
--- a/src/api/index.js
+++ b/src/api/index.js
@@ -27,8 +27,10 @@ class Steem extends EventEmitter {
         this._setLogger(options);
         this.options = options;
         this.seqNo = 0; // used for rpc calls
-        this.errorCount = 0;
-        this.apiIndex = 0;
+        this.error_count = 0;
+        this.api_index = 0;
+        this.error_threshold = 3;
+        this.alternative_api_endpoints = ['https://api.hive.blog', 'https://anyx.io'];
         methods.forEach(method => {
             const methodName = method.method_name || camelCase(method.method);
             const methodParams = method.params || [];
@@ -184,6 +186,12 @@ class Steem extends EventEmitter {
 
     setOptions(options) {
         Object.assign(this.options, options);
+
+        if (options.hasOwnProperty('failover_threshold'))
+            this.failover_threshold = options.failover_threshold;
+        if (options.hasOwnProperty('alternative_api_endpoints'))
+            this.alternative_api_endpoints = options.alternative_api_endpoints;
+
         this._setLogger(options);
         this._setTransport(options);
         this.transport.setOptions(options);
@@ -191,35 +199,22 @@ class Steem extends EventEmitter {
         {
           config.set( 'address_prefix', options.useTestNet ? 'TST' : 'STM' )
         }
-        if (options.hasOwnProperty('failover_threshold'))
-        {
-            config.set('failover_threshold', options.failover_threshold);
-        }
-        if (options.hasOwnProperty('alternative_api_endpoints'))
-        {
-            config.set('alternative_api_endpoints', options.alternative_api_endpoints);
-        }
+
         if (options.hasOwnProperty('url'))
         {
-            if (this.options.alternative_api_endpoints === undefined || this.options.alternative_api_endpoints === null)
-            {
-                console.log("no alternative api endpoints found, can't update the index");
-            }
-            let index = 0;
-            for (var i = 0; i < this.options.alternative_api_endpoints.length; i++)
+            let new_index = 0;
+            for (var i = 0; i < this.alternative_api_endpoints.length; i++)
             {
-                if (this.options.url === this.options.alternative_api_endpoints[i])
+                let temp_endpoint = this.alternative_api_endpoints[i];
+                if (temp_endpoint === options.url)
                 {
-                    index = i;
+                    new_index = i;
                     break;
                 }
             }
-            this.apiIndex = index;
-            console.log("updated apiIndex to be ", this.apiIndex);
+            this.api_index = new_index;
+            let new_endpoint = this.alternative_api_endpoints[this.api_index];
         }
-
-        console.log("done setting options. new options are: ", this.options);
-        console.log("does failover_threshold still exist? ", this.options.failover_threshold === 'undefined' ? "no" : "yes");
     }
 
     setWebSocket(url) {
@@ -382,26 +377,31 @@ class Steem extends EventEmitter {
 
     notifyError(err, ignore=false)
     {
-        this.errorCount++;
         if (ignore)
         {
             return;
         }
-        if (this.options.failover_threshold === 'undefined')
+        if (this.failover_threshold === undefined || this.alternative_api_endpoints === undefined)
+        {
+            return;
+        }
+        if (err && err.toString().includes("overseer"))
         {
-            console.log("no failover options are listed, can't failover");
+            //overseer was a steem thing, it doesn't exist in hive so don't count this error towards failover
             return;
         }
-        if (this.errorCount >= this.options.failover_threshold)
+        this.error_count++;
+        if (this.error_count >= this.failover_threshold)
         {
-            console.log("failing over");
-            this.errorCount = 0;
-            this.apiIndex++;
-            if (this.apiIndex >= this.options.alternative_api_endpoints.length)
+            let current_url = this.options.url;
+            this.error_count = 0;
+            this.api_index++;
+            if (this.api_index >= this.alternative_api_endpoints.length)
             {
-                this.apiIndex = 0;
+                this.api_index = 0;
             }
-            let nextEndpoint = this.options.alternative_api_endpoints[this.apiIndex];
+            let nextEndpoint = this.alternative_api_endpoints[this.api_index];
+            console.log("failing over. old endpoint was: ", current_url, " new one is: ", nextEndpoint);
             this.setOptions({url: nextEndpoint});
         }
     }
diff --git a/src/api/transports/http.js b/src/api/transports/http.js
index e030d80..9ce59e7 100644
--- a/src/api/transports/http.js
+++ b/src/api/transports/http.js
@@ -45,7 +45,6 @@ export function jsonRpc(uri, {method, id, params, fetchMethod=fetch}) {
       throw new Error(`Invalid response id: ${ rpcRes.id }`);
     }
     if (rpcRes.error) {
-      console.log("rcpRes error means rpc threw an error. uri, payload are: ", uri, payload);
       throw new RPCError(rpcRes.error);
     }
     return rpcRes.result
diff --git a/src/config.js b/src/config.js
deleted file mode 100644
index e4febd8..0000000
--- a/src/config.js
+++ /dev/null
@@ -1,24 +0,0 @@
-import each from 'lodash/each';
-const defaultConfig = require('../config.json');
-
-class Config {
-  constructor(c) {
-    each(c, (value, key) => {
-      this[key] = value;
-    });
-  }
-
-  get(k) {
-    return this[k];
-  }
-
-  set(k, v) {
-    this[k] = v;
-  }
-}
-
-module.exports = new Config(defaultConfig);
-if(typeof module.exports.Config !== 'undefined') {
-  throw new Error("default config.json file may not contain a property 'Config'");
-}
-module.exports.Config = Config;
-- 
GitLab