Index: chrome/browser/resources/google_now/utility.js |
diff --git a/chrome/browser/resources/google_now/utility.js b/chrome/browser/resources/google_now/utility.js |
index d0153bcc4c816bf22eccdda08914766e26d2efff..921907022d9e3e315c5c005c921b55bbc4ba2894 100644 |
--- a/chrome/browser/resources/google_now/utility.js |
+++ b/chrome/browser/resources/google_now/utility.js |
@@ -221,3 +221,99 @@ function buildTaskManager(areConflicting) { |
wrapCallback: wrapCallback |
}; |
} |
+ |
+var storage = chrome.storage.local; |
+ |
+/** |
+ * Builds an object to manage retrying activities with exponential backoff. |
+ * @param {string} name Name of this attempt manager. |
+ * @param {function()} attempt Activity that the manager retries till it |
skare_
2013/05/14 02:03:52
nit: expand till->until
vadimt
2013/05/14 18:47:50
Done.
|
+ * calls 'stop' method. |
+ * @param {number} initialDelaySeconds Default first delay until first retry. |
+ * @param {number} maximumDelaySeconds Maximum delay between retries. |
+ * @return {Object} Attempt manager interface. |
+ */ |
+function buildAttemptManager( |
+ name, attempt, initialDelaySeconds, maximumDelaySeconds) { |
+ var alarmName = name + '-scheduler'; |
+ var currentDelayStorageKey = name + '-current-delay'; |
+ |
+ /** |
+ * Creates an alarm for the next attempt. The alarm is repeating for the case |
+ * when the next attempt crashes before registering next alarm. |
+ * @param {number} delaySeconds Delay until next retry. |
+ */ |
+ function createAlarm(delaySeconds) { |
+ var alarmInfo = { |
+ delayInMinutes: delaySeconds / 60, |
+ periodInMinutes: maximumDelaySeconds / 60 |
+ }; |
+ chrome.alarms.create(alarmName, alarmInfo); |
+ } |
+ |
+ /** |
+ * Schedules next attempt. |
+ * @param {number=} opt_previousDelaySeconds Previous delay in a sequence of |
+ * retry attemps, if specified. Not specified for scheduling first retry |
rgustafson
2013/05/14 01:25:17
attempts
vadimt
2013/05/14 18:47:50
Done.
|
+ * in the exponential sequence. |
+ */ |
+ function scheduleNextAttempt(opt_previousDelaySeconds) { |
+ var base = opt_previousDelaySeconds ? opt_previousDelaySeconds * 2 : |
skare_
2013/05/14 02:03:52
it's likely this isn't a concern since this isn't
vadimt
2013/05/14 18:47:50
No. Anyways, we'd need to special-case 0, otherwis
|
+ initialDelaySeconds; |
+ var newRetryDelaySeconds = |
+ Math.min(base * (1 + 0.2 * Math.random()), maximumDelaySeconds); |
+ |
+ createAlarm(newRetryDelaySeconds); |
+ |
+ var items = {}; |
+ items[currentDelayStorageKey] = newRetryDelaySeconds; |
+ storage.set(items); |
+ } |
+ |
+ /** |
+ * Starts repeated attempts. |
+ * @param {number=} opt_firstDelaySeconds Time until the first attempt, if |
+ * specified. Otherwise, initialDelaySeconds will be used for the first |
+ * attempt. |
+ */ |
+ function start(opt_firstDelaySeconds) { |
+ if (opt_firstDelaySeconds) { |
+ createAlarm(opt_firstDelaySeconds); |
+ storage.remove(currentDelayStorageKey); |
+ } else { |
+ scheduleNextAttempt(); |
+ } |
+ } |
+ |
+ /** |
+ * Stops repeated attempts. |
+ */ |
+ function stop() { |
+ chrome.alarms.clear(alarmName); |
+ storage.remove(currentDelayStorageKey); |
+ } |
+ |
+ /** |
+ * Plans for the next attempt. |
+ * @param {function()} callback Completion callback. |
+ */ |
+ function planForNext(callback) { |
rgustafson
2013/05/14 01:25:17
The wording of this confused me too. At the least,
vadimt
2013/05/14 18:47:50
Done.
|
+ tasks.debugSetStepName('planForNext-get-storage'); |
+ storage.get(currentDelayStorageKey, function(items) { |
+ console.log('planForNext-get-storage ' + JSON.stringify(items)); |
+ scheduleNextAttempt(items[currentDelayStorageKey]); |
rgustafson
2013/05/14 01:25:17
This value isn't going to exist if you call this a
vadimt
2013/05/14 18:47:50
Yes, in this case, we start from the default value
|
+ callback(); |
+ }); |
+ } |
+ |
+ chrome.alarms.onAlarm.addListener(function(alarm) { |
+ if (alarm.name == alarmName) |
+ attempt(); |
+ }); |
+ |
+ return { |
+ start: start, |
+ planForNext: planForNext, |
+ stop: stop |
+ }; |
+} |