Skip to content
Permalink
9bfb9ba527
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
132 lines (132 sloc) 5.75 KB
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
import { __extends } from "tslib";
import * as utils from "../util/utils";
import { BaseRequestPolicy, } from "./requestPolicy";
import { RestError } from "../restError";
export function exponentialRetryPolicy(retryCount, retryInterval, minRetryInterval, maxRetryInterval) {
return {
create: function (nextPolicy, options) {
return new ExponentialRetryPolicy(nextPolicy, options, retryCount, retryInterval, minRetryInterval, maxRetryInterval);
},
};
}
var DEFAULT_CLIENT_RETRY_INTERVAL = 1000 * 30;
var DEFAULT_CLIENT_RETRY_COUNT = 3;
var DEFAULT_CLIENT_MAX_RETRY_INTERVAL = 1000 * 90;
var DEFAULT_CLIENT_MIN_RETRY_INTERVAL = 1000 * 3;
/**
* @class
* Instantiates a new "ExponentialRetryPolicyFilter" instance.
*/
var ExponentialRetryPolicy = /** @class */ (function (_super) {
__extends(ExponentialRetryPolicy, _super);
/**
* @constructor
* @param {RequestPolicy} nextPolicy The next RequestPolicy in the pipeline chain.
* @param {RequestPolicyOptionsLike} options The options for this RequestPolicy.
* @param {number} [retryCount] The client retry count.
* @param {number} [retryInterval] The client retry interval, in milliseconds.
* @param {number} [minRetryInterval] The minimum retry interval, in milliseconds.
* @param {number} [maxRetryInterval] The maximum retry interval, in milliseconds.
*/
function ExponentialRetryPolicy(nextPolicy, options, retryCount, retryInterval, minRetryInterval, maxRetryInterval) {
var _this = _super.call(this, nextPolicy, options) || this;
function isNumber(n) {
return typeof n === "number";
}
_this.retryCount = isNumber(retryCount) ? retryCount : DEFAULT_CLIENT_RETRY_COUNT;
_this.retryInterval = isNumber(retryInterval) ? retryInterval : DEFAULT_CLIENT_RETRY_INTERVAL;
_this.minRetryInterval = isNumber(minRetryInterval)
? minRetryInterval
: DEFAULT_CLIENT_MIN_RETRY_INTERVAL;
_this.maxRetryInterval = isNumber(maxRetryInterval)
? maxRetryInterval
: DEFAULT_CLIENT_MAX_RETRY_INTERVAL;
return _this;
}
ExponentialRetryPolicy.prototype.sendRequest = function (request) {
var _this = this;
return this._nextPolicy
.sendRequest(request.clone())
.then(function (response) { return retry(_this, request, response); })
.catch(function (error) { return retry(_this, request, error.response, undefined, error); });
};
return ExponentialRetryPolicy;
}(BaseRequestPolicy));
export { ExponentialRetryPolicy };
/**
* Determines if the operation should be retried and how long to wait until the next retry.
*
* @param {ExponentialRetryPolicy} policy The ExponentialRetryPolicy that this function is being called against.
* @param {number} statusCode The HTTP status code.
* @param {RetryData} retryData The retry data.
* @return {boolean} True if the operation qualifies for a retry; false otherwise.
*/
function shouldRetry(policy, statusCode, retryData) {
if (statusCode == undefined ||
(statusCode < 500 && statusCode !== 408) ||
statusCode === 501 ||
statusCode === 505) {
return false;
}
var currentCount;
if (!retryData) {
throw new Error("retryData for the ExponentialRetryPolicyFilter cannot be null.");
}
else {
currentCount = retryData && retryData.retryCount;
}
return currentCount < policy.retryCount;
}
/**
* Updates the retry data for the next attempt.
*
* @param {ExponentialRetryPolicy} policy The ExponentialRetryPolicy that this function is being called against.
* @param {RetryData} retryData The retry data.
* @param {RetryError} [err] The operation"s error, if any.
*/
function updateRetryData(policy, retryData, err) {
if (!retryData) {
retryData = {
retryCount: 0,
retryInterval: 0,
};
}
if (err) {
if (retryData.error) {
err.innerError = retryData.error;
}
retryData.error = err;
}
// Adjust retry count
retryData.retryCount++;
// Adjust retry interval
var incrementDelta = Math.pow(2, retryData.retryCount) - 1;
var boundedRandDelta = policy.retryInterval * 0.8 +
Math.floor(Math.random() * (policy.retryInterval * 1.2 - policy.retryInterval * 0.8));
incrementDelta *= boundedRandDelta;
retryData.retryInterval = Math.min(policy.minRetryInterval + incrementDelta, policy.maxRetryInterval);
return retryData;
}
function retry(policy, request, response, retryData, requestError) {
retryData = updateRetryData(policy, retryData, requestError);
var isAborted = request.abortSignal && request.abortSignal.aborted;
if (!isAborted && shouldRetry(policy, response && response.status, retryData)) {
return utils
.delay(retryData.retryInterval)
.then(function () { return policy._nextPolicy.sendRequest(request.clone()); })
.then(function (res) { return retry(policy, request, res, retryData, undefined); })
.catch(function (err) { return retry(policy, request, response, retryData, err); });
}
else if (isAborted || requestError || !response) {
// If the operation failed in the end, return all errors instead of just the last one
var err = retryData.error ||
new RestError("Failed to send the request.", RestError.REQUEST_SEND_ERROR, response && response.status, response && response.request, response);
return Promise.reject(err);
}
else {
return Promise.resolve(response);
}
}
//# sourceMappingURL=exponentialRetryPolicy.js.map