You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by db...@apache.org on 2017/02/09 17:06:34 UTC

ambari git commit: AMBARI-19939 Service Config pages load very slowly

Repository: ambari
Updated Branches:
  refs/heads/trunk ca09c208e -> dbb356774


AMBARI-19939 Service Config pages load very slowly


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/dbb35677
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/dbb35677
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/dbb35677

Branch: refs/heads/trunk
Commit: dbb3567740c9a2f5d48baab390c7f10711380f98
Parents: ca09c20
Author: Denys Buzhor <bd...@hortonworks.com>
Authored: Thu Feb 9 15:55:18 2017 +0200
Committer: Denys Buzhor <bd...@hortonworks.com>
Committed: Thu Feb 9 19:03:05 2017 +0200

----------------------------------------------------------------------
 .../controllers/main/service/info/configs.js    | 13 ++-
 .../app/mixins/common/configs/configs_loader.js |  2 +-
 .../app/mixins/common/track_request_mixin.js    | 36 +++++++-
 ambari-web/app/routes/main.js                   | 15 +++-
 .../main/host/configs_service_test.js           |  2 +
 .../test/controllers/main/host/details_test.js  |  1 +
 .../main/service/info/config_test.js            | 87 +++++++++++++++++++-
 .../common/configs/configs_loader_test.js       |  7 +-
 8 files changed, 148 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/dbb35677/ambari-web/app/controllers/main/service/info/configs.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/service/info/configs.js b/ambari-web/app/controllers/main/service/info/configs.js
index 319610c..c49bfae 100644
--- a/ambari-web/app/controllers/main/service/info/configs.js
+++ b/ambari-web/app/controllers/main/service/info/configs.js
@@ -235,6 +235,7 @@ App.MainServiceInfoConfigsController = Em.Controller.extend(App.AddSecurityConfi
    */
   clearStep: function () {
     this.abortRequests();
+    App.router.get('mainController').stopPolling();
     App.set('componentToBeAdded', {});
     App.set('componentToBeDeleted', {});
     this.clearLoadInfo();
@@ -288,7 +289,7 @@ App.MainServiceInfoConfigsController = Em.Controller.extend(App.AddSecurityConfi
       acc.push(i);
       return Array.prototype.concat.apply(acc, App.StackService.find(i).get('dependentServiceNames').toArray()).without(serviceName).uniq();
     }, []));
-    this.trackRequest(this.loadConfigTheme(serviceName).always(function () {
+    this.trackRequestChain(this.loadConfigTheme(serviceName).always(function () {
       if (self.get('preSelectedConfigVersion')) {
         self.loadPreSelectedConfigVersion();
       } else {
@@ -299,6 +300,16 @@ App.MainServiceInfoConfigsController = Em.Controller.extend(App.AddSecurityConfi
   },
 
   /**
+   * Turn on polling when all requests are finished
+   */
+  trackRequestsDidChange: function() {
+    var allCompleted = this.get('requestsInProgress').everyProperty('completed', true);
+    if (this.get('requestsInProgress').length && allCompleted) {
+      App.router.get('mainController').startPolling();
+    }
+  }.observes('requestsInProgress.@each.completed'),
+
+  /**
    * Generate "finger-print" for current <code>stepConfigs[0]</code>
    * Used to determine, if user has some unsaved changes (comparing with <code>hash</code>)
    * @returns {string|null}

http://git-wip-us.apache.org/repos/asf/ambari/blob/dbb35677/ambari-web/app/mixins/common/configs/configs_loader.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mixins/common/configs/configs_loader.js b/ambari-web/app/mixins/common/configs/configs_loader.js
index 666cef8..403b871 100644
--- a/ambari-web/app/mixins/common/configs/configs_loader.js
+++ b/ambari-web/app/mixins/common/configs/configs_loader.js
@@ -107,7 +107,7 @@ App.ConfigsLoader = Em.Mixin.create(App.GroupsMappingMixin, {
     this.set('versionLoaded', false);
     this.set('selectedVersion', this.get('currentDefaultVersion'));
     this.set('preSelectedConfigVersion', null);
-    this.trackRequest(App.ajax.send({
+    this.trackRequestChain(App.ajax.send({
       name: 'service.serviceConfigVersions.get.current',
       sender: this,
       data: {

http://git-wip-us.apache.org/repos/asf/ambari/blob/dbb35677/ambari-web/app/mixins/common/track_request_mixin.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mixins/common/track_request_mixin.js b/ambari-web/app/mixins/common/track_request_mixin.js
index 6fcc991..07eaf6e 100644
--- a/ambari-web/app/mixins/common/track_request_mixin.js
+++ b/ambari-web/app/mixins/common/track_request_mixin.js
@@ -28,7 +28,36 @@ App.TrackRequestMixin = Em.Mixin.create({
    * @method trackRequest
    */
   trackRequest: function (request) {
-    this.get('requestsInProgress').push(request);
+    var requestId = this.get('requestsInProgress').length;
+    var self = this;
+    this.get('requestsInProgress').pushObject({
+      request: request,
+      id: requestId,
+      status: request.state(),
+      completed: ['resolved', 'rejected'].contains(request.state())
+    });
+    request.always(function() {
+      Em.setProperties(self.get('requestsInProgress').findProperty('id', requestId), {
+        completed: true,
+        status: request.state()
+      });
+    });
+  },
+
+  /**
+   * This method used to put promise to requests queue which is waiting for another request to be put in tracking queue
+   * after tracking request promise will be completed. Basically it used for places where trackRequest called after
+   * tracked promise gets resolved.
+   *
+   * @param {$.ajax} request
+   */
+  trackRequestChain: function(request) {
+    var dfd = $.Deferred();
+    request.always(function() {
+      dfd.resolve();
+    });
+    this.trackRequest(request);
+    this.trackRequest(dfd);
   },
 
   /**
@@ -37,8 +66,9 @@ App.TrackRequestMixin = Em.Mixin.create({
    */
   abortRequests: function () {
     this.get('requestsInProgress').forEach(function(r) {
-      if (r && r.readyState !== 4) {
-        r.abort();
+      var request = r.request;
+      if (request && request.readyState !== undefined && request.readyState !== 4) {
+        request.abort();
       }
     });
     this.get('requestsInProgress').clear();

http://git-wip-us.apache.org/repos/asf/ambari/blob/dbb35677/ambari-web/app/routes/main.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/routes/main.js b/ambari-web/app/routes/main.js
index 354198b..9ed2dd1 100644
--- a/ambari-web/app/routes/main.js
+++ b/ambari-web/app/routes/main.js
@@ -229,7 +229,7 @@ module.exports = Em.Route.extend(App.RouterRedirections, {
             	    controller.connectOutlet('mainHostSummary');
             	  });
             	} else
-            	  controller.connectOutlet('mainHostSummary');  
+              controller.connectOutlet('mainHostSummary');
               });
             } else if(App.Service.find().mapProperty('serviceName').contains('HIVE')) {
               App.router.get('configurationController').getConfigsByTags(tags).always(function () {
@@ -718,6 +718,7 @@ module.exports = Em.Route.extend(App.RouterRedirections, {
             //if service is not existed then route to default service
             if (item.get('isLoaded')) {
               if (router.get('mainServiceItemController.isConfigurable')) {
+                router.get('mainController').stopPolling();
                 router.get('mainServiceItemController').connectOutlet('mainServiceInfoConfigs', item);
               }
               else {
@@ -730,13 +731,19 @@ module.exports = Em.Route.extend(App.RouterRedirections, {
             }
           });
         },
-        exitRoute: function (router, context, callback) {
+        exitRoute: function (router, nextRoute, callback) {
           var controller = router.get('mainServiceInfoConfigsController');
+          var exitCallback = function() {
+            if (!/\/main\/services\/\w+\/configs$/.test(nextRoute)) {
+              router.get('mainController').startPolling();
+            }
+            callback();
+          };
           // If another user is running some wizard, current user can't save configs
           if (controller.hasUnsavedChanges() && !router.get('wizardWatcherController.isWizardRunning')) {
-            controller.showSavePopup(callback);
+            controller.showSavePopup(exitCallback);
           } else {
-            callback();
+            exitCallback();
           }
         }
       }),

http://git-wip-us.apache.org/repos/asf/ambari/blob/dbb35677/ambari-web/test/controllers/main/host/configs_service_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/main/host/configs_service_test.js b/ambari-web/test/controllers/main/host/configs_service_test.js
index deb01ae..85f98b3 100644
--- a/ambari-web/test/controllers/main/host/configs_service_test.js
+++ b/ambari-web/test/controllers/main/host/configs_service_test.js
@@ -107,11 +107,13 @@ describe('App.MainHostServiceConfigsController', function () {
       sinon.stub(controller, 'loadConfigTheme', function() {
         return { always: Em.K };
       });
+      sinon.stub(controller, 'trackRequest');
     });
     afterEach(function() {
       controller.loadCurrentVersions.restore();
       controller.loadConfigTheme.restore();
       App.themesMapper.generateAdvancedTabs.restore();
+      controller.trackRequest.restore();
     });
 		it("should set host", function () {
 			controller.set('content', {

http://git-wip-us.apache.org/repos/asf/ambari/blob/dbb35677/ambari-web/test/controllers/main/host/details_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/main/host/details_test.js b/ambari-web/test/controllers/main/host/details_test.js
index 7f3fcf7..17b1eec 100644
--- a/ambari-web/test/controllers/main/host/details_test.js
+++ b/ambari-web/test/controllers/main/host/details_test.js
@@ -38,6 +38,7 @@ describe('App.MainHostDetailsController', function () {
 
   beforeEach(function () {
     controller = getController();
+    sinon.stub(controller, 'trackRequest');
   });
 
   App.TestAliases.testAsComputedFilterBy(getController(), 'serviceNonClientActiveComponents', 'serviceActiveComponents', 'isClient', false);

http://git-wip-us.apache.org/repos/asf/ambari/blob/dbb35677/ambari-web/test/controllers/main/service/info/config_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/main/service/info/config_test.js b/ambari-web/test/controllers/main/service/info/config_test.js
index ce98c0c..8ca48b1 100644
--- a/ambari-web/test/controllers/main/service/info/config_test.js
+++ b/ambari-web/test/controllers/main/service/info/config_test.js
@@ -38,6 +38,8 @@ describe("App.MainServiceInfoConfigsController", function () {
 
   beforeEach(function () {
     sinon.stub(App.themesMapper, 'generateAdvancedTabs').returns(Em.K);
+    sinon.stub(App.router.get('mainController'), 'startPolling');
+    sinon.stub(App.router.get('mainController'), 'stopPolling');
     mainServiceInfoConfigsController = getController();
   });
 
@@ -45,6 +47,8 @@ describe("App.MainServiceInfoConfigsController", function () {
 
   afterEach(function() {
     App.themesMapper.generateAdvancedTabs.restore();
+    App.router.get('mainController').startPolling.restore();
+    App.router.get('mainController').stopPolling.restore();
   });
 
   describe("#getHash", function () {
@@ -256,12 +260,14 @@ describe("App.MainServiceInfoConfigsController", function () {
       sinon.stub(mainServiceInfoConfigsController, "getHash", function () {
         return "hash"
       });
+      sinon.stub(mainServiceInfoConfigsController, 'trackRequest');
     });
 
     afterEach(function () {
       mainServiceInfoConfigsController.get.restore();
       mainServiceInfoConfigsController.restartServicePopup.restore();
       mainServiceInfoConfigsController.getHash.restore();
+      mainServiceInfoConfigsController.trackRequest.restore();
     });
 
     tests.forEach(function (t) {
@@ -822,9 +828,86 @@ describe("App.MainServiceInfoConfigsController", function () {
       mainServiceInfoConfigsController.get('requestsInProgress').clear();
     });
     it("should set requestsInProgress", function () {
+      var dfd = $.Deferred();
       mainServiceInfoConfigsController.get('requestsInProgress').clear();
-      mainServiceInfoConfigsController.trackRequest({'request': {}});
-      expect(mainServiceInfoConfigsController.get('requestsInProgress')[0]).to.eql({'request': {}});
+      mainServiceInfoConfigsController.trackRequest(dfd);
+      expect(mainServiceInfoConfigsController.get('requestsInProgress')[0]).to.eql(
+        {
+          request: dfd,
+          id: 0,
+          status: 'pending',
+          completed: false
+        }
+      );
+    });
+    it('should update request status when it become resolved', function() {
+      var request = $.Deferred();
+      mainServiceInfoConfigsController.get('requestsInProgress').clear();
+      mainServiceInfoConfigsController.trackRequest(request);
+      expect(mainServiceInfoConfigsController.get('requestsInProgress')[0]).to.eql({
+        request: request,
+        id: 0,
+        status: 'pending',
+        completed: false
+      });
+      request.resolve();
+      expect(mainServiceInfoConfigsController.get('requestsInProgress')[0]).to.eql({
+        request: request,
+        id: 0,
+        status: 'resolved',
+        completed: true
+      });
+    });
+  });
+
+  describe('#trackRequestChain', function() {
+    beforeEach(function() {
+      mainServiceInfoConfigsController.get('requestsInProgress').clear();
+    });
+    it('should set 2 requests in to requestsInProgress list', function() {
+      mainServiceInfoConfigsController.trackRequestChain($.Deferred());
+      expect(mainServiceInfoConfigsController.get('requestsInProgress')).to.have.length(2);
+    });
+    it('should update status for both requests when tracked requests become resolved', function() {
+      var request = $.Deferred(),
+          requests;
+      mainServiceInfoConfigsController.trackRequestChain(request);
+      requests = mainServiceInfoConfigsController.get('requestsInProgress');
+      assert.deepEqual(requests.mapProperty('status'), ['pending', 'pending'], 'initial statuses');
+      assert.deepEqual(requests.mapProperty('completed'), [false, false], 'initial completed');
+      request.reject();
+      assert.deepEqual(requests.mapProperty('status'), ['rejected', 'resolved'], 'update status when rejected');
+      assert.deepEqual(requests.mapProperty('completed'), [true, true], 'initial complete are false');
+    });
+  });
+
+  describe('#abortRequests', function() {
+    beforeEach(function() {
+      mainServiceInfoConfigsController.get('requestsInProgress').clear();
+    });
+    it('should clear requests when abort called', function() {
+      mainServiceInfoConfigsController.trackRequest($.Deferred());
+      mainServiceInfoConfigsController.abortRequests();
+      expect(mainServiceInfoConfigsController.get('requestsInProgress')).to.have.length(0);
+    });
+    it('should abort requests which are not finished', function() {
+      var pendingRequest = {
+        abort: sinon.spy(),
+        readyState: 0,
+        state: sinon.spy(),
+        always: sinon.spy()
+      };
+      var finishedRequest = {
+        abort: sinon.spy(),
+        readyState: 4,
+        state: sinon.spy(),
+        always: sinon.spy()
+      };
+      mainServiceInfoConfigsController.trackRequest(pendingRequest);
+      mainServiceInfoConfigsController.trackRequest(finishedRequest);
+      mainServiceInfoConfigsController.abortRequests();
+      expect(pendingRequest.abort.calledOnce).to.be.true;
+      expect(finishedRequest.abort.calledOnce).to.be.false;
     });
   });
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/dbb35677/ambari-web/test/mixins/common/configs/configs_loader_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/mixins/common/configs/configs_loader_test.js b/ambari-web/test/mixins/common/configs/configs_loader_test.js
index 8f22b44..749e5d3 100644
--- a/ambari-web/test/mixins/common/configs/configs_loader_test.js
+++ b/ambari-web/test/mixins/common/configs/configs_loader_test.js
@@ -223,14 +223,14 @@ describe('App.ConfigsLoader', function() {
   describe("#loadCurrentVersions()", function () {
 
     beforeEach(function() {
-      sinon.stub(mixin, 'trackRequest');
+      sinon.stub(mixin, 'trackRequestChain');
       mixin.set('currentDefaultVersion', {});
       mixin.set('servicesToLoad', ['S1', 'S2']);
       mixin.loadCurrentVersions();
     });
 
     afterEach(function() {
-      mixin.trackRequest.restore();
+      mixin.trackRequestChain.restore();
     });
 
     it("isCompareMode should be false", function() {
@@ -250,7 +250,7 @@ describe('App.ConfigsLoader', function() {
     });
 
     it("trackRequest should be called", function() {
-      expect(mixin.trackRequest.calledOnce).to.be.true;
+      expect(mixin.trackRequestChain.calledOnce).to.be.true;
     });
 
     it("App.ajax.send should be called", function() {
@@ -490,4 +490,3 @@ describe('App.ConfigsLoader', function() {
   });
 
 });
-