systemErrorRetryPolicy.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. // Copyright (c) Microsoft Corporation. All rights reserved.
  2. // Licensed under the MIT License. See License.txt in the project root for license information.
  3. import * as tslib_1 from "tslib";
  4. import * as utils from "../util/utils";
  5. import { BaseRequestPolicy } from "./requestPolicy";
  6. export function systemErrorRetryPolicy(retryCount, retryInterval, minRetryInterval, maxRetryInterval) {
  7. return {
  8. create: function (nextPolicy, options) {
  9. return new SystemErrorRetryPolicy(nextPolicy, options, retryCount, retryInterval, minRetryInterval, maxRetryInterval);
  10. }
  11. };
  12. }
  13. /**
  14. * @class
  15. * Instantiates a new "ExponentialRetryPolicyFilter" instance.
  16. *
  17. * @constructor
  18. * @param {number} retryCount The client retry count.
  19. * @param {number} retryInterval The client retry interval, in milliseconds.
  20. * @param {number} minRetryInterval The minimum retry interval, in milliseconds.
  21. * @param {number} maxRetryInterval The maximum retry interval, in milliseconds.
  22. */
  23. var SystemErrorRetryPolicy = /** @class */ (function (_super) {
  24. tslib_1.__extends(SystemErrorRetryPolicy, _super);
  25. function SystemErrorRetryPolicy(nextPolicy, options, retryCount, retryInterval, minRetryInterval, maxRetryInterval) {
  26. var _this = _super.call(this, nextPolicy, options) || this;
  27. _this.DEFAULT_CLIENT_RETRY_INTERVAL = 1000 * 30;
  28. _this.DEFAULT_CLIENT_RETRY_COUNT = 3;
  29. _this.DEFAULT_CLIENT_MAX_RETRY_INTERVAL = 1000 * 90;
  30. _this.DEFAULT_CLIENT_MIN_RETRY_INTERVAL = 1000 * 3;
  31. _this.retryCount = typeof retryCount === "number" ? retryCount : _this.DEFAULT_CLIENT_RETRY_COUNT;
  32. _this.retryInterval = typeof retryInterval === "number" ? retryInterval : _this.DEFAULT_CLIENT_RETRY_INTERVAL;
  33. _this.minRetryInterval = typeof minRetryInterval === "number" ? minRetryInterval : _this.DEFAULT_CLIENT_MIN_RETRY_INTERVAL;
  34. _this.maxRetryInterval = typeof maxRetryInterval === "number" ? maxRetryInterval : _this.DEFAULT_CLIENT_MAX_RETRY_INTERVAL;
  35. return _this;
  36. }
  37. SystemErrorRetryPolicy.prototype.sendRequest = function (request) {
  38. var _this = this;
  39. return this._nextPolicy.sendRequest(request.clone()).then(function (response) { return retry(_this, request, response); });
  40. };
  41. return SystemErrorRetryPolicy;
  42. }(BaseRequestPolicy));
  43. export { SystemErrorRetryPolicy };
  44. /**
  45. * Determines if the operation should be retried and how long to wait until the next retry.
  46. *
  47. * @param {number} statusCode The HTTP status code.
  48. * @param {RetryData} retryData The retry data.
  49. * @return {boolean} True if the operation qualifies for a retry; false otherwise.
  50. */
  51. function shouldRetry(policy, retryData) {
  52. var currentCount;
  53. if (!retryData) {
  54. throw new Error("retryData for the SystemErrorRetryPolicyFilter cannot be null.");
  55. }
  56. else {
  57. currentCount = (retryData && retryData.retryCount);
  58. }
  59. return (currentCount < policy.retryCount);
  60. }
  61. /**
  62. * Updates the retry data for the next attempt.
  63. *
  64. * @param {RetryData} retryData The retry data.
  65. * @param {object} err The operation"s error, if any.
  66. */
  67. function updateRetryData(policy, retryData, err) {
  68. if (!retryData) {
  69. retryData = {
  70. retryCount: 0,
  71. retryInterval: 0
  72. };
  73. }
  74. if (err) {
  75. if (retryData.error) {
  76. err.innerError = retryData.error;
  77. }
  78. retryData.error = err;
  79. }
  80. // Adjust retry count
  81. retryData.retryCount++;
  82. // Adjust retry interval
  83. var incrementDelta = Math.pow(2, retryData.retryCount) - 1;
  84. var boundedRandDelta = policy.retryInterval * 0.8 +
  85. Math.floor(Math.random() * (policy.retryInterval * 1.2 - policy.retryInterval * 0.8));
  86. incrementDelta *= boundedRandDelta;
  87. retryData.retryInterval = Math.min(policy.minRetryInterval + incrementDelta, policy.maxRetryInterval);
  88. return retryData;
  89. }
  90. function retry(policy, request, operationResponse, retryData, err) {
  91. retryData = updateRetryData(policy, retryData, err);
  92. if (err && err.code && shouldRetry(policy, retryData) &&
  93. (err.code === "ETIMEDOUT" || err.code === "ESOCKETTIMEDOUT" || err.code === "ECONNREFUSED" ||
  94. err.code === "ECONNRESET" || err.code === "ENOENT")) {
  95. // If previous operation ended with an error and the policy allows a retry, do that
  96. return utils.delay(retryData.retryInterval)
  97. .then(function () { return policy._nextPolicy.sendRequest(request.clone()); })
  98. .then(function (res) { return retry(policy, request, res, retryData, err); })
  99. .catch(function (err) { return retry(policy, request, operationResponse, retryData, err); });
  100. }
  101. else {
  102. if (err != undefined) {
  103. // If the operation failed in the end, return all errors instead of just the last one
  104. err = retryData.error;
  105. return Promise.reject(err);
  106. }
  107. return Promise.resolve(operationResponse);
  108. }
  109. }
  110. //# sourceMappingURL=systemErrorRetryPolicy.js.map