diff options
author | Jarkko Pöyry <jpoyry@google.com> | 2015-05-21 14:56:02 -0700 |
---|---|---|
committer | Jarkko Pöyry <jpoyry@google.com> | 2015-07-28 20:18:13 -0700 |
commit | f6b3b95d6fc51e6cc9daf3d51521115ebec039b8 (patch) | |
tree | 97b0428805b69661f0b63cdd2f0561a946ac3b33 | |
parent | 3d47cd0b46acd2f8b5e71ca572ac46474afbe78e (diff) | |
download | cherry-f6b3b95d6fc51e6cc9daf3d51521115ebec039b8.tar.gz |
Limit test group and leaf controller updates to that scope.
Change-Id: I50e8b09643c36217c375e18bc99e4e613e5545dd
-rw-r--r-- | client/js/app.js | 2 | ||||
-rw-r--r-- | client/js/batchResult.js | 10 | ||||
-rw-r--r-- | client/js/services.js | 93 |
3 files changed, 81 insertions, 24 deletions
diff --git a/client/js/app.js b/client/js/app.js index 1a5127c..1dd91d9 100644 --- a/client/js/app.js +++ b/client/js/app.js @@ -19,6 +19,8 @@ var debugStr = function(val) { var str = JSON.stringify(val); + if (str === undefined) + return 'undefined'; if (str.length > 100) return str.slice(0, 97) + "..."; return str; diff --git a/client/js/batchResult.js b/client/js/batchResult.js index 9c3509b..7ae04a9 100644 --- a/client/js/batchResult.js +++ b/client/js/batchResult.js @@ -235,7 +235,7 @@ angular.module('cherry.batchResult', []) .controller('TestGroupStatsCtrl', ['$scope', '$stateParams', 'rtdb', 'rpc', function($scope, $stateParams, rtdb, rpc) { var objId = $stateParams.batchResultId + '/' + $stateParams.testGroupPath; - rtdb.bind('TestCaseTreeGroup', objId, $scope); + rtdb.bind('TestCaseTreeGroup', objId, $scope, { invalidateMode: 'scope' }); $scope.testGroupPath = $stateParams.testGroupPath; @@ -304,7 +304,7 @@ angular.module('cherry.batchResult', []) init: function(objId) { - rtdb.bind('TestCaseTreeGroup', objId, $scope); + rtdb.bind('TestCaseTreeGroup', objId, $scope, { invalidateMode: 'scope' }); }, getNumResults: function() @@ -381,11 +381,7 @@ angular.module('cherry.batchResult', []) // \note obj can be either a header object's id (a string) or the header object itself. if (_.isString(obj)) { - // \note object binding is done asynchronously to avoid stalling UI for long (when opening large sub-trees) - setTimeout(function() - { - rtdb.bind('TestCaseHeader', obj, $scope, { onUpdate:onUpdate }); - }, 0); + rtdb.bind('TestCaseHeader', obj, $scope, { onUpdate: onUpdate, invalidateMode: 'scope' }); } else { diff --git a/client/js/services.js b/client/js/services.js index 08cd25a..89e8c93 100644 --- a/client/js/services.js +++ b/client/js/services.js @@ -65,19 +65,12 @@ angular.module('cherry.services', []) var flushInMsgs = function(items) { - // \note scope.$apply is wrapped in setTimeout to avoid calling it while angular's digest is already active. - setTimeout(function() + for (var msgNdx = 0; msgNdx < items.length; msgNdx++) { - $rootScope.$apply(function () - { - for (var msgNdx = 0; msgNdx < items.length; msgNdx++) - { - var msgArgs = items[msgNdx]; - for (var ndx = 0; ndx < msgHandlers.length; ndx++) - msgHandlers[ndx].call(null, socket, msgArgs); // \todo [petri] this? - } - }); - }, 0); + var msgArgs = items[msgNdx]; + for (var ndx = 0; ndx < msgHandlers.length; ndx++) + msgHandlers[ndx].call(null, socket, msgArgs); // \todo [petri] this? + } }; var inMsgQueue = new BatchQueue(flushInMsgs, 100); @@ -277,7 +270,7 @@ angular.module('cherry.services', []) }; }]) -.factory('rtdb', ['socket', 'rpc', function(socket, rpc) +.factory('rtdb', ['$rootScope', 'socket', 'rpc', function($rootScope, socket, rpc) { console.log('[rtdb] init'); var subscribedObjects = {}; // objectKey(objType, objId): {count:<int>, obj:<obj>} @@ -612,10 +605,64 @@ angular.module('cherry.services', []) versionViewedObjectGetQueue.enqueue({ view: view, objType: objType, objId: objId, onUpdate: onUpdate }); }; + var applyBoundDataUpdates = function(items) + { + for (var ndx = 0; ndx < items.length; ++ndx) + { + var scope = items[ndx].scope; + var valueName = items[ndx].valueName; + var value = items[ndx].value; + var onUpdateCb = items[ndx].onUpdateCb; + var objType = items[ndx].objType; + var objId = items[ndx].objId; + + scope[valueName] = value; + if (onUpdateCb) + onUpdateCb(objType, objId, value); + } + }; + + var flushRootInvalidateUpdates = function(items) + { + applyBoundDataUpdates(items); + $rootScope.$digest(); + }; + var flushScopeInvalidateUpdates = function(items) + { + applyBoundDataUpdates(items); + + // apply in order + + var scopeList = []; + for (var itemNdx = 0; itemNdx < items.length; ++itemNdx) + { + var seenScope = false; + for (var scopeNdx = 0; scopeNdx < scopeList.length; ++scopeNdx) + { + if (scopeList[scopeNdx] === items[itemNdx].scope) + { + seenScope = true; + break; + } + } + + if (!seenScope) + scopeList.push(items[itemNdx].scope); + } + + for (var ndx = 0; ndx < scopeList.length; ++ndx) + scopeList[ndx].$digest(); + }; + + var rootInvalidateUpdateQueue = new BatchQueue(flushRootInvalidateUpdates, 10); + var scopeInvalidateUpdateQueue = new BatchQueue(flushScopeInvalidateUpdates, 20); + var bind = function(objType, objId, scope, options) { options = options || {}; var valueName = options.valueName || 'value'; + var invalidateMode = options.invalidateMode || 'root'; + var onUpdateCb = options.onUpdate || null; var initial = {}; initial[valueName] = null; @@ -623,10 +670,22 @@ angular.module('cherry.services', []) var onUpdate = function(obj) { - scope[valueName] = obj; - - if (options.onUpdate) - options.onUpdate(objType, objId, obj); + if (invalidateMode === "root") + { + rootInvalidateUpdateQueue.enqueue({ scope: scope, valueName: valueName, value: obj, objType: objType, objId: objId, onUpdateCb: onUpdateCb }); + } + else if (invalidateMode === "scope") + { + scopeInvalidateUpdateQueue.enqueue({ scope: scope, valueName: valueName, value: obj, objType: objType, objId: objId, onUpdateCb: onUpdateCb }); + } + else if (invalidateMode === "none") + { + scope[valueName] = obj; + if (onUpdateCb) + onUpdateCb(objType, objId, obj); + } + else + throw "Invalid mode: " + debugStr(invalidateMode); }; if (scope.rtdbVersionView && scope.rtdbVersionView.id !== undefined) |