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() {
});
});
-