Skip to content

Commit 2c3f827

Browse files
committed
MOBILE-925 delegates: Fix async finish order problems in delegates
1 parent 94985a4 commit 2c3f827

File tree

8 files changed

+342
-107
lines changed

8 files changed

+342
-107
lines changed

www/addons/mod/quiz/services/accessrulesdelegate.js

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ angular.module('mm.addons.mod_quiz')
5151
var handlers = {},
5252
enabledHandlers = {},
5353
self = {},
54-
updatePromises = {};
54+
updatePromises = {},
55+
lastUpdateHandlersStart;
5556

5657
/**
5758
* Get the handler for a certain rule.
@@ -108,6 +109,23 @@ angular.module('mm.addons.mod_quiz')
108109
return typeof enabledHandlers[ruleName] != 'undefined';
109110
};
110111

112+
/**
113+
* Check if a time belongs to the last update handlers call.
114+
* This is to handle the cases where updateHandlers don't finish in the same order as they're called.
115+
*
116+
* @module mm.addons.mod_quiz
117+
* @ngdoc method
118+
* @name $mmaModQuizAccessRulesDelegate#isLastUpdateCall
119+
* @param {Number} time Time to check.
120+
* @return {Boolean} True if equal, false otherwise.
121+
*/
122+
self.isLastUpdateCall = function(time) {
123+
if (!lastUpdateHandlersStart) {
124+
return true;
125+
}
126+
return time == lastUpdateHandlersStart;
127+
};
128+
111129
/**
112130
* Given a list of rules, check if preflight check is required.
113131
*
@@ -279,10 +297,11 @@ angular.module('mm.addons.mod_quiz')
279297
* @name $mmaModQuizAccessRulesDelegate#updateHandler
280298
* @param {String} ruleName The name of the rule this handler handles.
281299
* @param {Object} handlerInfo The handler details.
300+
* @param {Number} time Time this update process started.
282301
* @return {Promise} Resolved when done.
283302
* @protected
284303
*/
285-
self.updateHandler = function(ruleName, handlerInfo) {
304+
self.updateHandler = function(ruleName, handlerInfo, time) {
286305
var promise,
287306
deleted = false,
288307
siteId = $mmSite.getId();
@@ -308,8 +327,9 @@ angular.module('mm.addons.mod_quiz')
308327
promise = promise.catch(function() {
309328
return false;
310329
}).then(function(enabled) {
330+
// Verify that this call is the last one that was started.
311331
// Check that site hasn't changed since the check started.
312-
if ($mmSite.isLoggedIn() && $mmSite.getId() === siteId) {
332+
if (self.isLastUpdateCall(time) && $mmSite.isLoggedIn() && $mmSite.getId() === siteId) {
313333
if (enabled) {
314334
enabledHandlers[ruleName] = handlerInfo.instance;
315335
} else {
@@ -338,13 +358,16 @@ angular.module('mm.addons.mod_quiz')
338358
* @protected
339359
*/
340360
self.updateHandlers = function() {
341-
var promises = [];
361+
var promises = [],
362+
now = new Date().getTime();
342363

343364
$log.debug('Updating handlers for current site.');
344365

366+
lastUpdateHandlersStart = now;
367+
345368
// Loop over all the handlers.
346369
angular.forEach(handlers, function(handlerInfo, ruleName) {
347-
promises.push(self.updateHandler(ruleName, handlerInfo));
370+
promises.push(self.updateHandler(ruleName, handlerInfo, now));
348371
});
349372

350373
return $q.all(promises).then(function() {

www/core/components/course/services/delegate.js

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ angular.module('mm.core.course')
7474

7575
self.$get = function($q, $log, $mmSite, $mmUtil, $mmCourseContentHandler) {
7676
var enabledHandlers = {},
77-
self = {};
77+
self = {},
78+
lastUpdateHandlersStart = {};
7879

7980
$log = $log.getInstance('$mmCourseDelegate');
8081

@@ -101,6 +102,23 @@ angular.module('mm.core.course')
101102
return $mmCourseContentHandler.getController(module, courseid, sectionid);
102103
};
103104

105+
/**
106+
* Check if a time belongs to the last update handlers call.
107+
* This is to handle the cases where updateContentHandlers don't finish in the same order as they're called.
108+
*
109+
* @module mm.core.course
110+
* @ngdoc method
111+
* @name $mmCourseDelegate#isLastUpdateCall
112+
* @param {Number} time Time to check.
113+
* @return {Boolean} True if equal, false otherwise.
114+
*/
115+
self.isLastUpdateCall = function(time) {
116+
if (!lastUpdateHandlersStart) {
117+
return true;
118+
}
119+
return time == lastUpdateHandlersStart;
120+
};
121+
104122
/**
105123
* Update the enabled handlers for the current site.
106124
*
@@ -109,11 +127,13 @@ angular.module('mm.core.course')
109127
* @name $mmCourseDelegate#updateContentHandler
110128
* @param {String} handles The module this handler handles, e.g. forum, label. This value will be compared with
111129
* @param {Object} handlerInfo The handler details.
130+
* @param {Number} time Time this update process started.
112131
* @return {Promise} Resolved when enabled, rejected when not.
113132
* @protected
114133
*/
115-
self.updateContentHandler = function(handles, handlerInfo) {
116-
var promise;
134+
self.updateContentHandler = function(handles, handlerInfo, time) {
135+
var promise,
136+
siteId = $mmSite.getId();
117137

118138
if (typeof handlerInfo.instance === 'undefined') {
119139
handlerInfo.instance = $mmUtil.resolveObject(handlerInfo.handler, true);
@@ -126,14 +146,17 @@ angular.module('mm.core.course')
126146
}
127147

128148
// Checks if the content is enabled.
129-
return promise.then(function(enabled) {
130-
if (enabled) {
131-
enabledHandlers[handles] = handlerInfo.instance;
132-
} else {
133-
return $q.reject();
149+
return promise.catch(function() {
150+
return false;
151+
}).then(function(enabled) {
152+
// Verify that this call is the last one that was started.
153+
if (self.isLastUpdateCall(time) && $mmSite.isLoggedIn() && $mmSite.getId() === siteId) {
154+
if (enabled) {
155+
enabledHandlers[handles] = handlerInfo.instance;
156+
} else {
157+
delete enabledHandlers[handles];
158+
}
134159
}
135-
}).catch(function() {
136-
delete enabledHandlers[handles];
137160
});
138161
};
139162

@@ -148,13 +171,15 @@ angular.module('mm.core.course')
148171
*/
149172
self.updateContentHandlers = function() {
150173
var promises = [],
151-
enabledHandlers = {};
174+
now = new Date().getTime();
152175

153176
$log.debug('Updating content handlers for current site.');
154177

178+
lastUpdateHandlersStart = now;
179+
155180
// Loop over all the content handlers.
156181
angular.forEach(contentHandlers, function(handlerInfo, handles) {
157-
promises.push(self.updateContentHandler(handles, handlerInfo));
182+
promises.push(self.updateContentHandler(handles, handlerInfo, now));
158183
});
159184

160185
return $q.all(promises).then(function() {

www/core/components/course/services/prefetchdelegate.js

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,8 @@ angular.module('mm.core')
8080
var enabledHandlers = {},
8181
self = {},
8282
deferreds = {},
83-
statusCache = {}; // To speed up the getModulesStatus function.
83+
statusCache = {}, // To speed up the getModulesStatus function.
84+
lastUpdateHandlersStart;
8485

8586
$log = $log.getInstance('$mmCoursePrefetchDelegate');
8687

@@ -335,6 +336,23 @@ angular.module('mm.core')
335336
return deferreds[$mmSite.getId()] && deferreds[$mmSite.getId()][id];
336337
};
337338

339+
/**
340+
* Check if a time belongs to the last update handlers call.
341+
* This is to handle the cases where updatePrefetchHandlers don't finish in the same order as they're called.
342+
*
343+
* @module mm.core
344+
* @ngdoc method
345+
* @name $mmCoursePrefetchDelegate#isLastUpdateCall
346+
* @param {Number} time Time to check.
347+
* @return {Boolean} True if equal, false otherwise.
348+
*/
349+
self.isLastUpdateCall = function(time) {
350+
if (!lastUpdateHandlersStart) {
351+
return true;
352+
}
353+
return time == lastUpdateHandlersStart;
354+
};
355+
338356
/**
339357
* Check if a module is downloadable.
340358
*
@@ -436,11 +454,13 @@ angular.module('mm.core')
436454
* @name $mmCoursePrefetchDelegate#updatePrefetchHandler
437455
* @param {String} handles The module this handler handles, e.g. forum, label.
438456
* @param {Object} handlerInfo The handler details.
457+
* @param {Number} time Time this update process started.
439458
* @return {Promise} Resolved when enabled, rejected when not.
440459
* @protected
441460
*/
442-
self.updatePrefetchHandler = function(handles, handlerInfo) {
443-
var promise;
461+
self.updatePrefetchHandler = function(handles, handlerInfo, time) {
462+
var promise,
463+
siteId = $mmSite.getId();
444464

445465
if (typeof handlerInfo.instance === 'undefined') {
446466
handlerInfo.instance = $mmUtil.resolveObject(handlerInfo.handler, true);
@@ -453,14 +473,18 @@ angular.module('mm.core')
453473
}
454474

455475
// Checks if the prefetch is enabled.
456-
return promise.then(function(enabled) {
457-
if (enabled) {
458-
enabledHandlers[handles] = handlerInfo.instance;
459-
} else {
460-
return $q.reject();
476+
return promise.catch(function() {
477+
return false;
478+
}).then(function(enabled) {
479+
// Verify that this call is the last one that was started.
480+
// Check that site hasn't changed since the check started.
481+
if (self.isLastUpdateCall(time) && $mmSite.isLoggedIn() && $mmSite.getId() === siteId) {
482+
if (enabled) {
483+
enabledHandlers[handles] = handlerInfo.instance;
484+
} else {
485+
delete enabledHandlers[handles];
486+
}
461487
}
462-
}).catch(function() {
463-
delete enabledHandlers[handles];
464488
});
465489
};
466490

@@ -474,13 +498,16 @@ angular.module('mm.core')
474498
* @protected
475499
*/
476500
self.updatePrefetchHandlers = function() {
477-
var promises = [];
501+
var promises = [],
502+
now = new Date().getTime();
478503

479504
$log.debug('Updating prefetch handlers for current site.');
480505

506+
lastUpdateHandlersStart = now;
507+
481508
// Loop over all the prefetch handlers.
482509
angular.forEach(prefetchHandlers, function(handlerInfo, handles) {
483-
promises.push(self.updatePrefetchHandler(handles, handlerInfo));
510+
promises.push(self.updatePrefetchHandler(handles, handlerInfo, now));
484511
});
485512

486513
return $q.all(promises).then(function() {

0 commit comments

Comments
 (0)