Path: blob/trunk/third_party/closure/goog/math/exponentialbackoff.js
2868 views
// Copyright 2011 The Closure Library Authors. All Rights Reserved.1//2// Licensed under the Apache License, Version 2.0 (the "License");3// you may not use this file except in compliance with the License.4// You may obtain a copy of the License at5//6// http://www.apache.org/licenses/LICENSE-2.07//8// Unless required by applicable law or agreed to in writing, software9// distributed under the License is distributed on an "AS-IS" BASIS,10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.11// See the License for the specific language governing permissions and12// limitations under the License.131415/**16* @fileoverview Utility class to manage the mathematics behind computing an17* exponential backoff model. Given an initial backoff value and a maximum18* backoff value, every call to backoff() will double the value until maximum19* backoff value is reached.20*21*/222324goog.provide('goog.math.ExponentialBackoff');2526goog.require('goog.asserts');27282930/**31* @struct32* @constructor33*34* @param {number} initialValue The initial backoff value.35* @param {number} maxValue The maximum backoff value.36* @param {number=} opt_randomFactor When set, adds randomness to the backoff37* and decay to avoid a thundering herd problem. Should be a number between38* 0 and 1, where 0 means no randomness and 1 means a factor of 0x to 2x.39* @param {number=} opt_backoffFactor The factor to backoff by. Defaults to 2.40* Should be a number greater than 1.41* @param {number=} opt_decayFactor The factor to decay by. Defaults to 2.42* Should be a number between greater than one.43*/44goog.math.ExponentialBackoff = function(45initialValue, maxValue, opt_randomFactor, opt_backoffFactor,46opt_decayFactor) {47goog.asserts.assert(48initialValue > 0, 'Initial value must be greater than zero.');49goog.asserts.assert(50maxValue >= initialValue,51'Max value should be at least as large as initial value.');5253if (goog.isDef(opt_randomFactor)) {54goog.asserts.assert(55opt_randomFactor >= 0 && opt_randomFactor <= 1,56'Randomness factor should be between 0 and 1.');57}5859if (goog.isDef(opt_backoffFactor)) {60goog.asserts.assert(61opt_backoffFactor > 1, 'Backoff factor should be greater than 1');62}6364if (goog.isDef(opt_decayFactor)) {65goog.asserts.assert(66opt_decayFactor >= 1, 'Decay factor should be greater than 1');67}6869/**70* @type {number}71* @private72*/73this.initialValue_ = initialValue;7475/**76* @type {number}77* @private78*/79this.maxValue_ = maxValue;8081/**82* The current backoff value.83* @type {number}84* @private85*/86this.currValue_ = initialValue;8788/**89* The current backoff value minus the random wait (if there is any).90* @type {number}91* @private92*/93this.currBaseValue_ = initialValue;9495/**96* The random factor to apply to the backoff value to avoid a thundering herd97* problem. Should be a number between 0 and 1, where 0 means no randomness98* and 1 means a factor of 0x to 2x.99* @type {number}100* @private101*/102this.randomFactor_ = opt_randomFactor || 0;103104/**105* Factor to backoff by.106* @type {number}107* @private108*/109this.backoffFactor_ = opt_backoffFactor || 2;110111/**112* Factor to decay by.113* @type {number}114* @private115*/116this.decayFactor_ = opt_decayFactor || 2;117};118119120/**121* The number of backoffs that have happened.122* @type {number}123* @private124*/125goog.math.ExponentialBackoff.prototype.currBackoffCount_ = 0;126127128/**129* The number of decays that have happened.130* @type {number}131* @private132*/133goog.math.ExponentialBackoff.prototype.currDecayCount_ = 0;134135136/**137* Resets the backoff value to its initial value.138*/139goog.math.ExponentialBackoff.prototype.reset = function() {140this.currValue_ = this.initialValue_;141this.currBaseValue_ = this.initialValue_;142this.currBackoffCount_ = 0;143this.currDecayCount_ = 0;144};145146147/**148* @return {number} The current backoff value.149*/150goog.math.ExponentialBackoff.prototype.getValue = function() {151return this.currValue_;152};153154155/**156* @return {number} The number of times this class has backed off.157*/158goog.math.ExponentialBackoff.prototype.getBackoffCount = function() {159return this.currBackoffCount_;160};161162163/**164* @return {number} The number of times this class has decayed.165*/166goog.math.ExponentialBackoff.prototype.getDecayCount = function() {167return this.currDecayCount_;168};169170171/**172* Initiates a backoff.173*/174goog.math.ExponentialBackoff.prototype.backoff = function() {175// If we haven't hit the maximum value yet, keep increasing the base value.176this.currBaseValue_ =177Math.min(this.maxValue_, this.currBaseValue_ * this.backoffFactor_);178179var randomWait = this.randomFactor_ ?180Math.round(181this.randomFactor_ * (Math.random() - 0.5) * 2 *182this.currBaseValue_) :1830;184this.currValue_ = Math.min(this.maxValue_, this.currBaseValue_ + randomWait);185this.currBackoffCount_++;186};187188189/**190* Initiates a decay.191*/192goog.math.ExponentialBackoff.prototype.decay = function() {193// If we haven't hit the initial value yet, keep decreasing the base value.194this.currBaseValue_ =195Math.max(this.initialValue_, this.currBaseValue_ / this.decayFactor_);196197var randomWait = this.randomFactor_ ?198Math.round(199this.randomFactor_ * (Math.random() - 0.5) * 2 *200this.currBaseValue_) :2010;202this.currValue_ =203Math.max(this.initialValue_, this.currBaseValue_ + randomWait);204this.currDecayCount_++;205};206207208