[polari/wip/kunaljain/multiple-server: 3/4] application: Try alternative servers on connection failures



commit c6700b516aa3bc0ef8ee615ccbc27e1796a04859
Author: Kunaal Jain <kunaalus gmail com>
Date:   Sat Apr 2 10:24:42 2016 +0530

    application: Try alternative servers on connection failures
    
    On predefined conncetions we have list of servers.
    There are times when one of the server is down, hence in
    case of connection failures try alternative servers.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=762335

 src/application.js     |   46 +++++++++++++++++++++++++++++++++++++++-------
 src/networksManager.js |    7 +++++++
 2 files changed, 46 insertions(+), 7 deletions(-)
---
diff --git a/src/application.js b/src/application.js
index b6fa847..37b6b38 100644
--- a/src/application.js
+++ b/src/application.js
@@ -347,10 +347,22 @@ const Application = new Lang.Class({
         account.update_parameters_vardict_async(asv, [], callback);
     },
 
+    _updateAccountServer: function(account, server, callback) {
+        let sv = { server: GLib.Variant.new('s', server.address),
+                   port: GLib.Variant.new('u', server.port) };
+        let asv = GLib.Variant.new('a{sv}', sv);
+        account.update_parameters_vardict_async(asv, [], callback);
+    },
+
     _requestChannel: function(accountPath, targetType, targetId, time, callback) {
         // have this in AccountMonitor?
         let factory = Tp.AccountManager.dup().get_factory();
         let account = factory.ensure_account(accountPath, []);
+        let alternateServers = [];
+
+        // If predefined network, get alternate servers list
+        if (this._networksManager.getAccountIsPredefined(account))
+            alternateServers = this._networksManager.getNetworkServers(account.service);
 
         if (!account.enabled) {
             // if we are requesting a channel for a disabled account, we
@@ -375,7 +387,10 @@ const Application = new Lang.Class({
           time: time,
           retry: 0,
           originalNick: account.nickname,
-          callback: callback };
+          callback: callback,
+          alternateServers: alternateServers,
+          currentServerId: 0
+        };
 
         this._pendingRequests[roomId] = requestData;
 
@@ -394,7 +409,7 @@ const Application = new Lang.Class({
                                            this._onEnsureChannel, requestData));
     },
 
-    _retryRequest: function(requestData) {
+    _retryNickRequest: function(requestData) {
         let account = requestData.account;
 
         // Try again with a different nick
@@ -407,6 +422,17 @@ const Application = new Lang.Class({
             }));
     },
 
+    _retryServerRequest: function(requestData) {
+        let account = requestData.account;
+
+        // Try again with a alternate server
+        let server = requestData.alternateServers[requestData.currentServerId];
+        this._updateAccountServer(account, server, Lang.bind(this,
+            function() {
+                this._ensureChannel(requestData);
+            }));
+    },
+
     _onEnsureChannel: function(req, res, requestData) {
         let account = req.account;
         let channel = null;
@@ -422,14 +448,20 @@ const Application = new Lang.Class({
                 return;
             if (error == ConnectionError.ALREADY_CONNECTED &&
                 requestData.retry++ < MAX_RETRIES) {
-                    this._retryRequest(requestData);
+                    this._retryNickRequest(requestData);
                     return;
             }
 
-            if (error && error != ConnectionError.CANCELLED)
-                Utils.debug('Account %s disconnected with error %s'.format(
-                            account.get_path_suffix(),
-                            error.replace(Tp.ERROR_PREFIX + '.', '')));
+            if (error && error != ConnectionError.CANCELLED) {
+                if (++requestData.currentServerId < requestData.alternateServers.length) {
+                    this._retryServerRequest(requestData);
+                    return;
+                } else {
+                    Utils.debug('Account %s disconnected with error %s'.format(
+                                account.get_path_suffix(),
+                                error.replace(Tp.ERROR_PREFIX + '.', '')));
+                }
+            }
         } catch (e if e.matches(Tp.Error, Tp.Error.CANCELLED)) {
             // interrupted by user request, don't log
         } catch (e) {
diff --git a/src/networksManager.js b/src/networksManager.js
index 6b04261..2cd9313 100644
--- a/src/networksManager.js
+++ b/src/networksManager.js
@@ -84,6 +84,13 @@ const NetworksManager = new Lang.Class({
         };
     },
 
+    getNetworkServers: function(id) {
+        let network = this._lookupNetwork(id);
+        let sslServers = network.servers.filter(s => s.ssl);
+        return sslServers.length > 0 ? sslServers
+                                     : network.servers;
+    },
+
     getNetworkMatchTerms: function(id) {
         let network = this._lookupNetwork(id);
         let servers = network.servers.map(function(s) {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]