owltech
Version:
This a backend for OwlTech Company
152 lines • 5.34 kB
JavaScript
;
/*!
* Copyright 2017 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
Object.defineProperty(exports, "__esModule", { value: true });
const logger_1 = require("./logger");
/*
* @module firestore/backoff
* @private
*
* Contains backoff logic to facilitate RPC error handling. This class derives
* its implementation from the Firestore Mobile Web Client.
*
* @see https://github.com/firebase/firebase-js-sdk/blob/master/packages/firestore/src/remote/backoff.ts
*/
/*!
* The default initial backoff time in milliseconds after an error.
* Set to 1s according to https://cloud.google.com/apis/design/errors.
*/
const DEFAULT_BACKOFF_INITIAL_DELAY_MS = 1000;
/*!
* The default maximum backoff time in milliseconds.
*/
const DEFAULT_BACKOFF_MAX_DELAY_MS = 60 * 1000;
/*!
* The default factor to increase the backup by after each failed attempt.
*/
const DEFAULT_BACKOFF_FACTOR = 1.5;
/*!
* The default jitter to distribute the backoff attempts by (0 means no
* randomization, 1.0 means +/-50% randomization).
*/
const DEFAULT_JITTER_FACTOR = 1.0;
/*!
* The timeout handler used by `ExponentialBackoff`.
*/
let delayExecution = setTimeout;
/**
* Allows overriding of the timeout handler used by the exponential backoff
* implementation. If not invoked, we default to `setTimeout()`.
*
* Used only in testing.
*
* @private
* @param {function} handler A handler than matches the API of `setTimeout()`.
*/
function setTimeoutHandler(handler) {
delayExecution = handler;
}
exports.setTimeoutHandler = setTimeoutHandler;
/**
* A helper for running delayed tasks following an exponential backoff curve
* between attempts.
*
* Each delay is made up of a "base" delay which follows the exponential
* backoff curve, and a "jitter" (+/- 50% by default) that is calculated and
* added to the base delay. This prevents clients from accidentally
* synchronizing their delays causing spikes of load to the backend.
*
* @private
*/
class ExponentialBackoff {
constructor(options = {}) {
/**
* The backoff delay of the current attempt.
*
* @private
*/
this.currentBaseMs = 0;
this.initialDelayMs = options.initialDelayMs !== undefined ?
options.initialDelayMs :
DEFAULT_BACKOFF_INITIAL_DELAY_MS;
this.backoffFactor = options.backoffFactor !== undefined ?
options.backoffFactor :
DEFAULT_BACKOFF_FACTOR;
this.maxDelayMs = options.maxDelayMs !== undefined ?
options.maxDelayMs :
DEFAULT_BACKOFF_MAX_DELAY_MS;
this.jitterFactor = options.jitterFactor !== undefined ?
options.jitterFactor :
DEFAULT_JITTER_FACTOR;
}
/**
* Resets the backoff delay.
*
* The very next backoffAndWait() will have no delay. If it is called again
* (i.e. due to an error), initialDelayMs (plus jitter) will be used, and
* subsequent ones will increase according to the backoffFactor.
*
* @private
*/
reset() {
this.currentBaseMs = 0;
}
/**
* Resets the backoff delay to the maximum delay (e.g. for use after a
* RESOURCE_EXHAUSTED error).
*
* @private
*/
resetToMax() {
this.currentBaseMs = this.maxDelayMs;
}
/**
* Returns a promise that resolves after currentDelayMs, and increases the
* delay for any subsequent attempts.
*
* @return A Promise that resolves when the current delay elapsed.
* @private
*/
backoffAndWait() {
// First schedule using the current base (which may be 0 and should be
// honored as such).
const delayWithJitterMs = this.currentBaseMs + this.jitterDelayMs();
if (this.currentBaseMs > 0) {
logger_1.logger('ExponentialBackoff.backoffAndWait', null, `Backing off for ${delayWithJitterMs} ms ` +
`(base delay: ${this.currentBaseMs} ms)`);
}
// Apply backoff factor to determine next delay and ensure it is within
// bounds.
this.currentBaseMs *= this.backoffFactor;
this.currentBaseMs = Math.max(this.currentBaseMs, this.initialDelayMs);
this.currentBaseMs = Math.min(this.currentBaseMs, this.maxDelayMs);
return new Promise(resolve => {
delayExecution(resolve, delayWithJitterMs);
});
}
/**
* Returns a randomized "jitter" delay based on the current base and jitter
* factor.
*
* @returns {number} The jitter to apply based on the current delay.
* @private
*/
jitterDelayMs() {
return (Math.random() - 0.5) * this.jitterFactor * this.currentBaseMs;
}
}
exports.ExponentialBackoff = ExponentialBackoff;
//# sourceMappingURL=backoff.js.map