UNPKG

5.89 kBJavaScriptView Raw
1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the MIT License. See License.txt in the project root for license information.
3import { __extends } from "tslib";
4import * as utils from "../util/utils";
5import { BaseRequestPolicy, } from "./requestPolicy";
6import { RestError } from "../restError";
7export function exponentialRetryPolicy(retryCount, retryInterval, minRetryInterval, maxRetryInterval) {
8 return {
9 create: function (nextPolicy, options) {
10 return new ExponentialRetryPolicy(nextPolicy, options, retryCount, retryInterval, minRetryInterval, maxRetryInterval);
11 },
12 };
13}
14var DEFAULT_CLIENT_RETRY_INTERVAL = 1000 * 30;
15var DEFAULT_CLIENT_RETRY_COUNT = 3;
16var DEFAULT_CLIENT_MAX_RETRY_INTERVAL = 1000 * 90;
17var DEFAULT_CLIENT_MIN_RETRY_INTERVAL = 1000 * 3;
18/**
19 * @class
20 * Instantiates a new "ExponentialRetryPolicyFilter" instance.
21 */
22var ExponentialRetryPolicy = /** @class */ (function (_super) {
23 __extends(ExponentialRetryPolicy, _super);
24 /**
25 * @constructor
26 * @param {RequestPolicy} nextPolicy The next RequestPolicy in the pipeline chain.
27 * @param {RequestPolicyOptionsLike} options The options for this RequestPolicy.
28 * @param {number} [retryCount] The client retry count.
29 * @param {number} [retryInterval] The client retry interval, in milliseconds.
30 * @param {number} [minRetryInterval] The minimum retry interval, in milliseconds.
31 * @param {number} [maxRetryInterval] The maximum retry interval, in milliseconds.
32 */
33 function ExponentialRetryPolicy(nextPolicy, options, retryCount, retryInterval, minRetryInterval, maxRetryInterval) {
34 var _this = _super.call(this, nextPolicy, options) || this;
35 function isNumber(n) {
36 return typeof n === "number";
37 }
38 _this.retryCount = isNumber(retryCount) ? retryCount : DEFAULT_CLIENT_RETRY_COUNT;
39 _this.retryInterval = isNumber(retryInterval) ? retryInterval : DEFAULT_CLIENT_RETRY_INTERVAL;
40 _this.minRetryInterval = isNumber(minRetryInterval)
41 ? minRetryInterval
42 : DEFAULT_CLIENT_MIN_RETRY_INTERVAL;
43 _this.maxRetryInterval = isNumber(maxRetryInterval)
44 ? maxRetryInterval
45 : DEFAULT_CLIENT_MAX_RETRY_INTERVAL;
46 return _this;
47 }
48 ExponentialRetryPolicy.prototype.sendRequest = function (request) {
49 var _this = this;
50 return this._nextPolicy
51 .sendRequest(request.clone())
52 .then(function (response) { return retry(_this, request, response); })
53 .catch(function (error) { return retry(_this, request, error.response, undefined, error); });
54 };
55 return ExponentialRetryPolicy;
56}(BaseRequestPolicy));
57export { ExponentialRetryPolicy };
58/**
59 * Determines if the operation should be retried and how long to wait until the next retry.
60 *
61 * @param {ExponentialRetryPolicy} policy The ExponentialRetryPolicy that this function is being called against.
62 * @param {number} statusCode The HTTP status code.
63 * @param {RetryData} retryData The retry data.
64 * @return {boolean} True if the operation qualifies for a retry; false otherwise.
65 */
66function shouldRetry(policy, statusCode, retryData) {
67 if (statusCode == undefined ||
68 (statusCode < 500 && statusCode !== 408) ||
69 statusCode === 501 ||
70 statusCode === 505) {
71 return false;
72 }
73 var currentCount;
74 if (!retryData) {
75 throw new Error("retryData for the ExponentialRetryPolicyFilter cannot be null.");
76 }
77 else {
78 currentCount = retryData && retryData.retryCount;
79 }
80 return currentCount < policy.retryCount;
81}
82/**
83 * Updates the retry data for the next attempt.
84 *
85 * @param {ExponentialRetryPolicy} policy The ExponentialRetryPolicy that this function is being called against.
86 * @param {RetryData} retryData The retry data.
87 * @param {RetryError} [err] The operation"s error, if any.
88 */
89function updateRetryData(policy, retryData, err) {
90 if (!retryData) {
91 retryData = {
92 retryCount: 0,
93 retryInterval: 0,
94 };
95 }
96 if (err) {
97 if (retryData.error) {
98 err.innerError = retryData.error;
99 }
100 retryData.error = err;
101 }
102 // Adjust retry count
103 retryData.retryCount++;
104 // Adjust retry interval
105 var incrementDelta = Math.pow(2, retryData.retryCount) - 1;
106 var boundedRandDelta = policy.retryInterval * 0.8 +
107 Math.floor(Math.random() * (policy.retryInterval * 1.2 - policy.retryInterval * 0.8));
108 incrementDelta *= boundedRandDelta;
109 retryData.retryInterval = Math.min(policy.minRetryInterval + incrementDelta, policy.maxRetryInterval);
110 return retryData;
111}
112function retry(policy, request, response, retryData, requestError) {
113 retryData = updateRetryData(policy, retryData, requestError);
114 var isAborted = request.abortSignal && request.abortSignal.aborted;
115 if (!isAborted && shouldRetry(policy, response && response.status, retryData)) {
116 return utils
117 .delay(retryData.retryInterval)
118 .then(function () { return policy._nextPolicy.sendRequest(request.clone()); })
119 .then(function (res) { return retry(policy, request, res, retryData, undefined); })
120 .catch(function (err) { return retry(policy, request, response, retryData, err); });
121 }
122 else if (isAborted || requestError || !response) {
123 // If the operation failed in the end, return all errors instead of just the last one
124 var err = retryData.error ||
125 new RestError("Failed to send the request.", RestError.REQUEST_SEND_ERROR, response && response.status, response && response.request, response);
126 return Promise.reject(err);
127 }
128 else {
129 return Promise.resolve(response);
130 }
131}
132//# sourceMappingURL=exponentialRetryPolicy.js.map
\No newline at end of file