зеркало из https://github.com/Azure/ms-rest-js.git
Add tests for exponentialRetryPolicyTests
This commit is contained in:
Родитель
8055d3c285
Коммит
d7d68fcee6
|
@ -39,9 +39,20 @@ var HttpHeaders = /** @class */ (function () {
|
|||
return !header ? undefined : header.value;
|
||||
};
|
||||
/**
|
||||
* Get the headers that are contained in this collection.
|
||||
* Get the headers that are contained this collection as an object.
|
||||
*/
|
||||
HttpHeaders.prototype.headers = function () {
|
||||
HttpHeaders.prototype.rawHeaders = function () {
|
||||
var result = {};
|
||||
for (var headerKey in this._headersMap) {
|
||||
var header = this._headersMap[headerKey];
|
||||
result[header.name] = header.value;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
/**
|
||||
* Get the headers that are contained in this collection as an array.
|
||||
*/
|
||||
HttpHeaders.prototype.headersArray = function () {
|
||||
var headers = [];
|
||||
for (var headerKey in this._headersMap) {
|
||||
headers.push(this._headersMap[headerKey]);
|
||||
|
@ -53,7 +64,7 @@ var HttpHeaders = /** @class */ (function () {
|
|||
*/
|
||||
HttpHeaders.prototype.headerNames = function () {
|
||||
var headerNames = [];
|
||||
var headers = this.headers();
|
||||
var headers = this.headersArray();
|
||||
for (var i = 0; i < headers.length; ++i) {
|
||||
headerNames.push(headers[i].name);
|
||||
}
|
||||
|
@ -64,7 +75,7 @@ var HttpHeaders = /** @class */ (function () {
|
|||
*/
|
||||
HttpHeaders.prototype.headerValues = function () {
|
||||
var headerValues = [];
|
||||
var headers = this.headers();
|
||||
var headers = this.headersArray();
|
||||
for (var i = 0; i < headers.length; ++i) {
|
||||
headerValues.push(headers[i].value);
|
||||
}
|
||||
|
@ -75,12 +86,18 @@ var HttpHeaders = /** @class */ (function () {
|
|||
*/
|
||||
HttpHeaders.prototype.toJson = function () {
|
||||
var result = {};
|
||||
var headers = this.headers();
|
||||
var headers = this.headersArray();
|
||||
for (var i = 0; i < headers.length; ++i) {
|
||||
result[headers[i].name] = headers[i].value;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
/**
|
||||
* Create a deep clone/copy of this HttpHeaders collection.
|
||||
*/
|
||||
HttpHeaders.prototype.clone = function () {
|
||||
return new HttpHeaders(this.rawHeaders());
|
||||
};
|
||||
return HttpHeaders;
|
||||
}());
|
||||
exports.HttpHeaders = HttpHeaders;
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"version":3,"file":"httpHeaders.js","sourceRoot":"","sources":["../../lib/httpHeaders.ts"],"names":[],"mappings":";AAAA,4DAA4D;AAC5D,+FAA+F;;AAE/F;;GAEG;AACH,sBAAsB,UAAkB;IACpC,OAAO,UAAU,CAAC,WAAW,EAAE,CAAC;AACpC,CAAC;AAsBD;;GAEG;AACH;IAGI,qBAAY,UAA2B;QACnC,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;QACtB,IAAI,UAAU,EAAE;YACZ,KAAK,IAAM,UAAU,IAAI,UAAU,EAAE;gBACjC,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC;aAChD;SACJ;IACL,CAAC;IAED;;;;;OAKG;IACI,yBAAG,GAAV,UAAW,UAAkB,EAAE,WAA4B;QACvD,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,CAAC,QAAQ,EAAE,EAAE,CAAC;IACrG,CAAC;IAED;;;;OAIG;IACI,yBAAG,GAAV,UAAW,UAAkB;QACzB,IAAM,MAAM,GAAe,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC;QACtE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;IAC9C,CAAC;IAED;;OAEG;IACI,6BAAO,GAAd;QACI,IAAM,OAAO,GAAiB,EAAE,CAAC;QACjC,KAAK,IAAM,SAAS,IAAI,IAAI,CAAC,WAAW,EAAE;YACtC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC;SAC7C;QACD,OAAO,OAAO,CAAC;IACnB,CAAC;IAED;;OAEG;IACI,iCAAW,GAAlB;QACI,IAAM,WAAW,GAAa,EAAE,CAAC;QACjC,IAAM,OAAO,GAAiB,IAAI,CAAC,OAAO,EAAE,CAAC;QAC7C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE;YACrC,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;SACrC;QACD,OAAO,WAAW,CAAC;IACvB,CAAC;IAED;;OAEG;IACI,kCAAY,GAAnB;QACI,IAAM,YAAY,GAAa,EAAE,CAAC;QAClC,IAAM,OAAO,GAAiB,IAAI,CAAC,OAAO,EAAE,CAAC;QAC7C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE;YACrC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;SACvC;QACD,OAAO,YAAY,CAAC;IACxB,CAAC;IAED;;OAEG;IACI,4BAAM,GAAb;QACI,IAAM,MAAM,GAAmB,EAAE,CAAC;QAElC,IAAM,OAAO,GAAiB,IAAI,CAAC,OAAO,EAAE,CAAC;QAC7C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE;YACrC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;SAC9C;QAED,OAAO,MAAM,CAAC;IAClB,CAAC;IACL,kBAAC;AAAD,CAAC,AAhFD,IAgFC;AAhFY,kCAAW"}
|
||||
{"version":3,"file":"httpHeaders.js","sourceRoot":"","sources":["../../lib/httpHeaders.ts"],"names":[],"mappings":";AAAA,4DAA4D;AAC5D,+FAA+F;;AAE/F;;GAEG;AACH,sBAAsB,UAAkB;IACpC,OAAO,UAAU,CAAC,WAAW,EAAE,CAAC;AACpC,CAAC;AAsBD;;GAEG;AACH;IAGI,qBAAY,UAA2B;QACnC,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;QACtB,IAAI,UAAU,EAAE;YACZ,KAAK,IAAM,UAAU,IAAI,UAAU,EAAE;gBACjC,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC;aAChD;SACJ;IACL,CAAC;IAED;;;;;OAKG;IACI,yBAAG,GAAV,UAAW,UAAkB,EAAE,WAA4B;QACvD,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,CAAC,QAAQ,EAAE,EAAE,CAAC;IACrG,CAAC;IAED;;;;OAIG;IACI,yBAAG,GAAV,UAAW,UAAkB;QACzB,IAAM,MAAM,GAAe,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC;QACtE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;IAC9C,CAAC;IAED;;OAEG;IACI,gCAAU,GAAjB;QACI,IAAM,MAAM,GAAmB,EAAE,CAAC;QAClC,KAAK,IAAM,SAAS,IAAI,IAAI,CAAC,WAAW,EAAE;YACtC,IAAM,MAAM,GAAe,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;YACvD,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC;SACtC;QACD,OAAO,MAAM,CAAC;IAClB,CAAC;IAED;;OAEG;IACI,kCAAY,GAAnB;QACI,IAAM,OAAO,GAAiB,EAAE,CAAC;QACjC,KAAK,IAAM,SAAS,IAAI,IAAI,CAAC,WAAW,EAAE;YACtC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC;SAC7C;QACD,OAAO,OAAO,CAAC;IACnB,CAAC;IAED;;OAEG;IACI,iCAAW,GAAlB;QACI,IAAM,WAAW,GAAa,EAAE,CAAC;QACjC,IAAM,OAAO,GAAiB,IAAI,CAAC,YAAY,EAAE,CAAC;QAClD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE;YACrC,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;SACrC;QACD,OAAO,WAAW,CAAC;IACvB,CAAC;IAED;;OAEG;IACI,kCAAY,GAAnB;QACI,IAAM,YAAY,GAAa,EAAE,CAAC;QAClC,IAAM,OAAO,GAAiB,IAAI,CAAC,YAAY,EAAE,CAAC;QAClD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE;YACrC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;SACvC;QACD,OAAO,YAAY,CAAC;IACxB,CAAC;IAED;;OAEG;IACI,4BAAM,GAAb;QACI,IAAM,MAAM,GAAmB,EAAE,CAAC;QAElC,IAAM,OAAO,GAAiB,IAAI,CAAC,YAAY,EAAE,CAAC;QAClD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE;YACrC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;SAC9C;QAED,OAAO,MAAM,CAAC;IAClB,CAAC;IAED;;OAEG;IACI,2BAAK,GAAZ;QACI,OAAO,IAAI,WAAW,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;IAC9C,CAAC;IACL,kBAAC;AAAD,CAAC,AAnGD,IAmGC;AAnGY,kCAAW"}
|
|
@ -7,61 +7,28 @@ var httpHeaders_1 = require("./httpHeaders");
|
|||
* An individual HTTP request that can be sent with a HttpClient.
|
||||
*/
|
||||
var HttpRequest = /** @class */ (function () {
|
||||
function HttpRequest(_httpMethod, _url, headers, _body) {
|
||||
this._httpMethod = _httpMethod;
|
||||
this._url = _url;
|
||||
this._body = _body;
|
||||
if (!this._url) {
|
||||
var urlString = (this._url === undefined || this._url === null ? this._url : "\"" + this._url + "\"");
|
||||
/**
|
||||
*
|
||||
* @param httpMethod The HTTP method that this request will use.
|
||||
* @param url The URL that this request will be sent to.
|
||||
* @param headers The HTTP headers that will be sent with this request.
|
||||
* @param body The body that will be sent with this request.
|
||||
*/
|
||||
function HttpRequest(httpMethod, url, headers, body) {
|
||||
this.httpMethod = httpMethod;
|
||||
this.url = url;
|
||||
this.body = body;
|
||||
if (!this.url) {
|
||||
var urlString = (this.url === undefined || this.url === null ? this.url : "\"" + this.url + "\"");
|
||||
throw new Error(urlString + " is not a valid URL for a HttpRequest.");
|
||||
}
|
||||
this._headers = (headers instanceof httpHeaders_1.HttpHeaders ? headers : new httpHeaders_1.HttpHeaders(headers));
|
||||
this.headers = (headers instanceof httpHeaders_1.HttpHeaders ? headers : new httpHeaders_1.HttpHeaders(headers));
|
||||
}
|
||||
Object.defineProperty(HttpRequest.prototype, "httpMethod", {
|
||||
/**
|
||||
* Get the HTTP method that this request will use.
|
||||
*/
|
||||
get: function () {
|
||||
return this._httpMethod;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(HttpRequest.prototype, "url", {
|
||||
/**
|
||||
* Get the URL that this request will be sent to.
|
||||
*/
|
||||
get: function () {
|
||||
return this._url;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(HttpRequest.prototype, "headers", {
|
||||
/**
|
||||
* Get the HTTP headers that will be sent with this request.
|
||||
*/
|
||||
get: function () {
|
||||
return this._headers;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(HttpRequest.prototype, "body", {
|
||||
/**
|
||||
* Get the body that will be sent with this request.
|
||||
*/
|
||||
get: function () {
|
||||
return this._body;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
/**
|
||||
* Create a deep clone/copy of this HttpRequest.
|
||||
*/
|
||||
HttpRequest.prototype.clone = function () {
|
||||
return JSON.parse(JSON.stringify(this));
|
||||
return new HttpRequest(this.httpMethod, this.url, this.headers.clone(), this.body);
|
||||
};
|
||||
return HttpRequest;
|
||||
}());
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"version":3,"file":"httpRequest.js","sourceRoot":"","sources":["../../lib/httpRequest.ts"],"names":[],"mappings":";;AAAA,4DAA4D;AAC5D,+FAA+F;AAC/F,6CAA4D;AAG5D;;GAEG;AACH;IAGI,qBAAoB,WAAuB,EAAU,IAAY,EAAE,OAAqC,EAAU,KAAc;QAA5G,gBAAW,GAAX,WAAW,CAAY;QAAU,SAAI,GAAJ,IAAI,CAAQ;QAAiD,UAAK,GAAL,KAAK,CAAS;QAC5H,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;YACZ,IAAM,SAAS,GAAW,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,OAAI,IAAI,CAAC,IAAI,OAAG,CAAC,CAAC;YACzG,MAAM,IAAI,KAAK,CAAI,SAAS,2CAAwC,CAAC,CAAC;SACzE;QAED,IAAI,CAAC,QAAQ,GAAG,CAAC,OAAO,YAAY,yBAAW,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,yBAAW,CAAC,OAAO,CAAC,CAAC,CAAC;IAC1F,CAAC;IAKD,sBAAW,mCAAU;QAHrB;;WAEG;aACH;YACI,OAAO,IAAI,CAAC,WAAW,CAAC;QAC5B,CAAC;;;OAAA;IAKD,sBAAW,4BAAG;QAHd;;WAEG;aACH;YACI,OAAO,IAAI,CAAC,IAAI,CAAC;QACrB,CAAC;;;OAAA;IAKD,sBAAW,gCAAO;QAHlB;;WAEG;aACH;YACI,OAAO,IAAI,CAAC,QAAQ,CAAC;QACzB,CAAC;;;OAAA;IAKD,sBAAW,6BAAI;QAHf;;WAEG;aACH;YACI,OAAO,IAAI,CAAC,KAAK,CAAC;QACtB,CAAC;;;OAAA;IAED;;OAEG;IACI,2BAAK,GAAZ;QACI,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;IAC5C,CAAC;IACL,kBAAC;AAAD,CAAC,AA9CD,IA8CC;AA9CY,kCAAW"}
|
||||
{"version":3,"file":"httpRequest.js","sourceRoot":"","sources":["../../lib/httpRequest.ts"],"names":[],"mappings":";;AAAA,4DAA4D;AAC5D,+FAA+F;AAC/F,6CAA4D;AAG5D;;GAEG;AACH;IAMI;;;;;;OAMG;IACH,qBAAmB,UAAsB,EAAS,GAAW,EAAE,OAAqC,EAAS,IAAa;QAAvG,eAAU,GAAV,UAAU,CAAY;QAAS,QAAG,GAAH,GAAG,CAAQ;QAAgD,SAAI,GAAJ,IAAI,CAAS;QACtH,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE;YACX,IAAM,SAAS,GAAW,CAAC,IAAI,CAAC,GAAG,KAAK,SAAS,IAAI,IAAI,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,OAAI,IAAI,CAAC,GAAG,OAAG,CAAC,CAAC;YACrG,MAAM,IAAI,KAAK,CAAI,SAAS,2CAAwC,CAAC,CAAC;SACzE;QAED,IAAI,CAAC,OAAO,GAAG,CAAC,OAAO,YAAY,yBAAW,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,yBAAW,CAAC,OAAO,CAAC,CAAC,CAAC;IACzF,CAAC;IAED;;OAEG;IACI,2BAAK,GAAZ;QACI,OAAO,IAAI,WAAW,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IACvF,CAAC;IACL,kBAAC;AAAD,CAAC,AA5BD,IA4BC;AA5BY,kCAAW"}
|
|
@ -0,0 +1,124 @@
|
|||
"use strict";
|
||||
var __extends = (this && this.__extends) || (function () {
|
||||
var extendStatics = Object.setPrototypeOf ||
|
||||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
||||
return function (d, b) {
|
||||
extendStatics(d, b);
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
})();
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||||
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||
function step(op) {
|
||||
if (f) throw new TypeError("Generator is already executing.");
|
||||
while (_) try {
|
||||
if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t;
|
||||
if (y = 0, t) op = [0, t.value];
|
||||
switch (op[0]) {
|
||||
case 0: case 1: t = op; break;
|
||||
case 4: _.label++; return { value: op[1], done: false };
|
||||
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||
default:
|
||||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||
if (t[2]) _.ops.pop();
|
||||
_.trys.pop(); continue;
|
||||
}
|
||||
op = body.call(thisArg, _);
|
||||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||
}
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var requestPolicy_1 = require("../requestPolicy");
|
||||
var utils = require("../util/utils");
|
||||
/**
|
||||
* Get a RequestPolicyFactory that creates ExponentialRetryPolicies.
|
||||
*/
|
||||
function exponentialRetryPolicy(retryOptions) {
|
||||
return function (nextPolicy, options) {
|
||||
return new ExponentialRetryPolicy(retryOptions || {}, nextPolicy, options);
|
||||
};
|
||||
}
|
||||
exports.exponentialRetryPolicy = exponentialRetryPolicy;
|
||||
var ExponentialRetryPolicy = /** @class */ (function (_super) {
|
||||
__extends(ExponentialRetryPolicy, _super);
|
||||
function ExponentialRetryPolicy(retryOptions, nextPolicy, options) {
|
||||
var _this = _super.call(this, nextPolicy, options) || this;
|
||||
_this._maximumAttempts = retryOptions.maximumAttempts || 3;
|
||||
_this._initialRetryDelayInMilliseconds = retryOptions.initialRetryDelayInMilliseconds || 30 * 1000;
|
||||
_this._maximumRetryDelayInMilliseconds = retryOptions.maximumRetryIntervalInMilliseconds || 90 * 1000;
|
||||
_this._delayFunction = retryOptions.delayFunction || utils.delay;
|
||||
return _this;
|
||||
}
|
||||
ExponentialRetryPolicy.prototype.send = function (request) {
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
var response, shouldAttempt, attemptNumber, attemptDelayInMilliseconds, responseError, statusCode, error_1, boundedRandomDelta, incrementDelta;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
shouldAttempt = true;
|
||||
attemptNumber = 0;
|
||||
attemptDelayInMilliseconds = this._initialRetryDelayInMilliseconds;
|
||||
_a.label = 1;
|
||||
case 1:
|
||||
if (!shouldAttempt) return [3 /*break*/, 8];
|
||||
_a.label = 2;
|
||||
case 2:
|
||||
_a.trys.push([2, 4, , 5]);
|
||||
++attemptNumber;
|
||||
return [4 /*yield*/, this._nextPolicy.send(request.clone())];
|
||||
case 3:
|
||||
response = _a.sent();
|
||||
if (response) {
|
||||
statusCode = response.statusCode;
|
||||
if ((statusCode < 500 && statusCode !== 408) || statusCode === 501 || statusCode === 505) {
|
||||
shouldAttempt = false;
|
||||
responseError = undefined;
|
||||
}
|
||||
}
|
||||
return [3 /*break*/, 5];
|
||||
case 4:
|
||||
error_1 = _a.sent();
|
||||
if (responseError) {
|
||||
error_1.innerError = responseError;
|
||||
}
|
||||
responseError = error_1;
|
||||
return [3 /*break*/, 5];
|
||||
case 5:
|
||||
shouldAttempt = shouldAttempt && attemptNumber < this._maximumAttempts;
|
||||
if (!shouldAttempt) return [3 /*break*/, 7];
|
||||
response = undefined;
|
||||
if (attemptNumber >= 2) {
|
||||
boundedRandomDelta = (attemptDelayInMilliseconds * 0.8) + Math.floor(Math.random() * attemptDelayInMilliseconds * 0.4);
|
||||
incrementDelta = (Math.pow(2, attemptNumber) - 1) * boundedRandomDelta;
|
||||
attemptDelayInMilliseconds = Math.min(attemptDelayInMilliseconds + incrementDelta, this._maximumRetryDelayInMilliseconds);
|
||||
}
|
||||
return [4 /*yield*/, this._delayFunction(attemptDelayInMilliseconds)];
|
||||
case 6:
|
||||
_a.sent();
|
||||
_a.label = 7;
|
||||
case 7: return [3 /*break*/, 1];
|
||||
case 8: return [2 /*return*/, response ? Promise.resolve(response) : Promise.reject(responseError)];
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
return ExponentialRetryPolicy;
|
||||
}(requestPolicy_1.BaseRequestPolicy));
|
||||
//# sourceMappingURL=exponentialRetryPolicy.js.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"exponentialRetryPolicy.js","sourceRoot":"","sources":["../../../lib/policies/exponentialRetryPolicy.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIA,kDAAoE;AAGpE,qCAAuC;AA2CvC;;GAEG;AACH,gCAAuC,YAA2B;IAC9D,OAAO,UAAC,UAAyB,EAAE,OAA6B;QAC5D,OAAO,IAAI,sBAAsB,CAAC,YAAY,IAAI,EAAE,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;IAC/E,CAAC,CAAC;AACN,CAAC;AAJD,wDAIC;AAED;IAAqC,0CAAiB;IAMlD,gCAAY,YAA0B,EAAE,UAAyB,EAAE,OAA6B;QAAhG,YACI,kBAAM,UAAU,EAAE,OAAO,CAAC,SAM7B;QAJG,KAAI,CAAC,gBAAgB,GAAG,YAAY,CAAC,eAAe,IAAI,CAAC,CAAC;QAC1D,KAAI,CAAC,gCAAgC,GAAG,YAAY,CAAC,+BAA+B,IAAI,EAAE,GAAG,IAAI,CAAC;QAClG,KAAI,CAAC,gCAAgC,GAAG,YAAY,CAAC,kCAAkC,IAAI,EAAE,GAAG,IAAI,CAAC;QACrG,KAAI,CAAC,cAAc,GAAG,YAAY,CAAC,aAAa,IAAI,KAAK,CAAC,KAAK,CAAC;;IACpE,CAAC;IAEY,qCAAI,GAAjB,UAAkB,OAAoB;;;;;;wBAE9B,aAAa,GAAG,IAAI,CAAC;wBACrB,aAAa,GAAG,CAAC,CAAC;wBAClB,0BAA0B,GAAW,IAAI,CAAC,gCAAgC,CAAC;;;6BAExE,aAAa;;;;wBAEZ,EAAE,aAAa,CAAC;wBACL,qBAAM,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,EAAA;;wBAAvD,QAAQ,GAAG,SAA4C,CAAC;wBAExD,IAAI,QAAQ,EAAE;4BACJ,UAAU,GAAW,QAAQ,CAAC,UAAU,CAAC;4BAC/C,IAAI,CAAC,UAAU,GAAG,GAAG,IAAI,UAAU,KAAK,GAAG,CAAC,IAAI,UAAU,KAAK,GAAG,IAAI,UAAU,KAAK,GAAG,EAAE;gCACtF,aAAa,GAAG,KAAK,CAAC;gCACtB,aAAa,GAAG,SAAS,CAAC;6BAC7B;yBACJ;;;;wBAED,IAAI,aAAa,EAAE;4BACf,OAAK,CAAC,UAAU,GAAG,aAAa,CAAC;yBACpC;wBACD,aAAa,GAAG,OAAK,CAAC;;;wBAG1B,aAAa,GAAG,aAAa,IAAI,aAAa,GAAG,IAAI,CAAC,gBAAgB,CAAC;6BACnE,aAAa,EAAb,wBAAa;wBACb,QAAQ,GAAG,SAAS,CAAC;wBAErB,IAAI,aAAa,IAAI,CAAC,EAAE;4BACd,kBAAkB,GAAW,CAAC,0BAA0B,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,0BAA0B,GAAG,GAAG,CAAC,CAAC;4BAC/H,cAAc,GAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,aAAa,CAAC,GAAG,CAAC,CAAC,GAAG,kBAAkB,CAAC;4BACrF,0BAA0B,GAAG,IAAI,CAAC,GAAG,CAAC,0BAA0B,GAAG,cAAc,EAAE,IAAI,CAAC,gCAAgC,CAAC,CAAC;yBAC7H;wBAED,qBAAM,IAAI,CAAC,cAAc,CAAC,0BAA0B,CAAC,EAAA;;wBAArD,SAAqD,CAAC;;;4BAG9D,sBAAO,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,EAAC;;;;KAC/E;IACL,6BAAC;AAAD,CAAC,AAvDD,CAAqC,iCAAiB,GAuDrD"}
|
|
@ -15,7 +15,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|||
var httpPipelineLogLevel_1 = require("../httpPipelineLogLevel");
|
||||
var requestPolicy_1 = require("../requestPolicy");
|
||||
/**
|
||||
* Get a RequestPolicyFactory that creates UserAgentRequestPolicies.
|
||||
* Get a RequestPolicyFactory that creates UserAgentPolicies.
|
||||
* @param userAgent The userAgent string to apply to each outgoing request.
|
||||
*/
|
||||
function userAgentPolicy(userAgent) {
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
"use strict";
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||||
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||
function step(op) {
|
||||
if (f) throw new TypeError("Generator is already executing.");
|
||||
while (_) try {
|
||||
if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t;
|
||||
if (y = 0, t) op = [0, t.value];
|
||||
switch (op[0]) {
|
||||
case 0: case 1: t = op; break;
|
||||
case 4: _.label++; return { value: op[1], done: false };
|
||||
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||
default:
|
||||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||
if (t[2]) _.ops.pop();
|
||||
_.trys.pop(); continue;
|
||||
}
|
||||
op = body.call(thisArg, _);
|
||||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||
}
|
||||
};
|
||||
var _this = this;
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
var assert = require("assert");
|
||||
var httpMethod_1 = require("../../lib/httpMethod");
|
||||
var httpRequest_1 = require("../../lib/httpRequest");
|
||||
var exponentialRetryPolicy_1 = require("../../lib/policies/exponentialRetryPolicy");
|
||||
var requestPolicyOptions_1 = require("../../lib/requestPolicyOptions");
|
||||
var inMemoryHttpResponse_1 = require("../inMemoryHttpResponse");
|
||||
describe("exponentialRetryPolicy", function () {
|
||||
it("should do nothing if no error occurs", function () { return __awaiter(_this, void 0, void 0, function () {
|
||||
var policyFactory, nextPolicy, policy, request, response;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
policyFactory = exponentialRetryPolicy_1.exponentialRetryPolicy({
|
||||
maximumAttempts: 3,
|
||||
initialRetryDelayInMilliseconds: 100,
|
||||
maximumRetryIntervalInMilliseconds: 1000
|
||||
});
|
||||
nextPolicy = {
|
||||
send: function (request) {
|
||||
request.headers.set("A", "B");
|
||||
return Promise.resolve(new inMemoryHttpResponse_1.InMemoryHttpResponse(request, 200, {}));
|
||||
}
|
||||
};
|
||||
policy = policyFactory(nextPolicy, new requestPolicyOptions_1.RequestPolicyOptions());
|
||||
request = new httpRequest_1.HttpRequest(httpMethod_1.HttpMethod.GET, "https://spam.com", {});
|
||||
return [4 /*yield*/, policy.send(request)];
|
||||
case 1:
|
||||
response = _a.sent();
|
||||
assert.deepStrictEqual(request, new httpRequest_1.HttpRequest(httpMethod_1.HttpMethod.GET, "https://spam.com", {}), "The original request should not be modified.");
|
||||
assert.deepStrictEqual(response.request, new httpRequest_1.HttpRequest(httpMethod_1.HttpMethod.GET, "https://spam.com", { "A": "B" }), "The request associated with the response should have the modified header.");
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); });
|
||||
it("should retry if an undefined HttpResponse is returned", function () { return __awaiter(_this, void 0, void 0, function () {
|
||||
var millisecondsDelayed, policyFactory, attempt, nextPolicy, policy, request, response;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
millisecondsDelayed = 0;
|
||||
policyFactory = exponentialRetryPolicy_1.exponentialRetryPolicy({
|
||||
maximumAttempts: 3,
|
||||
initialRetryDelayInMilliseconds: 30 * 1000,
|
||||
maximumRetryIntervalInMilliseconds: 90 * 1000,
|
||||
delayFunction: function (delayInMilliseconds) {
|
||||
millisecondsDelayed += delayInMilliseconds;
|
||||
return Promise.resolve();
|
||||
}
|
||||
});
|
||||
attempt = 0;
|
||||
nextPolicy = {
|
||||
send: function (request) {
|
||||
++attempt;
|
||||
request.headers.set("A", attempt);
|
||||
return Promise.resolve(attempt === 1 ? undefined : new inMemoryHttpResponse_1.InMemoryHttpResponse(request, 200, {}));
|
||||
}
|
||||
};
|
||||
policy = policyFactory(nextPolicy, new requestPolicyOptions_1.RequestPolicyOptions());
|
||||
request = new httpRequest_1.HttpRequest(httpMethod_1.HttpMethod.GET, "https://spam.com", {});
|
||||
return [4 /*yield*/, policy.send(request)];
|
||||
case 1:
|
||||
response = _a.sent();
|
||||
assert.deepStrictEqual(request, new httpRequest_1.HttpRequest(httpMethod_1.HttpMethod.GET, "https://spam.com", {}), "The original request should not be modified.");
|
||||
assert.deepStrictEqual(response.request, new httpRequest_1.HttpRequest(httpMethod_1.HttpMethod.GET, "https://spam.com", { "A": "2" }), "The request associated with the response should have the modified header.");
|
||||
assert.strictEqual(millisecondsDelayed, 30 * 1000);
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); });
|
||||
});
|
||||
//# sourceMappingURL=exponentialRetryPolicyTests.js.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"exponentialRetryPolicyTests.js","sourceRoot":"","sources":["../../../test/policies/exponentialRetryPolicyTests.ts"],"names":[],"mappings":"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"}
|
|
@ -64,9 +64,21 @@ export class HttpHeaders {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get the headers that are contained in this collection.
|
||||
* Get the headers that are contained this collection as an object.
|
||||
*/
|
||||
public headers(): HttpHeader[] {
|
||||
public rawHeaders(): RawHttpHeaders {
|
||||
const result: RawHttpHeaders = {};
|
||||
for (const headerKey in this._headersMap) {
|
||||
const header: HttpHeader = this._headersMap[headerKey];
|
||||
result[header.name] = header.value;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the headers that are contained in this collection as an array.
|
||||
*/
|
||||
public headersArray(): HttpHeader[] {
|
||||
const headers: HttpHeader[] = [];
|
||||
for (const headerKey in this._headersMap) {
|
||||
headers.push(this._headersMap[headerKey]);
|
||||
|
@ -79,7 +91,7 @@ export class HttpHeaders {
|
|||
*/
|
||||
public headerNames(): string[] {
|
||||
const headerNames: string[] = [];
|
||||
const headers: HttpHeader[] = this.headers();
|
||||
const headers: HttpHeader[] = this.headersArray();
|
||||
for (let i = 0; i < headers.length; ++i) {
|
||||
headerNames.push(headers[i].name);
|
||||
}
|
||||
|
@ -91,7 +103,7 @@ export class HttpHeaders {
|
|||
*/
|
||||
public headerValues(): string[] {
|
||||
const headerValues: string[] = [];
|
||||
const headers: HttpHeader[] = this.headers();
|
||||
const headers: HttpHeader[] = this.headersArray();
|
||||
for (let i = 0; i < headers.length; ++i) {
|
||||
headerValues.push(headers[i].value);
|
||||
}
|
||||
|
@ -104,11 +116,18 @@ export class HttpHeaders {
|
|||
public toJson(): RawHttpHeaders {
|
||||
const result: RawHttpHeaders = {};
|
||||
|
||||
const headers: HttpHeader[] = this.headers();
|
||||
const headers: HttpHeader[] = this.headersArray();
|
||||
for (let i = 0; i < headers.length; ++i) {
|
||||
result[headers[i].name] = headers[i].value;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a deep clone/copy of this HttpHeaders collection.
|
||||
*/
|
||||
public clone(): HttpHeaders {
|
||||
return new HttpHeaders(this.rawHeaders());
|
||||
}
|
||||
}
|
|
@ -7,49 +7,31 @@ import { HttpMethod } from "./httpMethod";
|
|||
* An individual HTTP request that can be sent with a HttpClient.
|
||||
*/
|
||||
export class HttpRequest {
|
||||
private readonly _headers: HttpHeaders;
|
||||
|
||||
constructor(private _httpMethod: HttpMethod, private _url: string, headers: HttpHeaders | RawHttpHeaders, private _body?: string) {
|
||||
if (!this._url) {
|
||||
const urlString: string = (this._url === undefined || this._url === null ? this._url : `"${this._url}"`);
|
||||
throw new Error(`${urlString} is not a valid URL for a HttpRequest.`);
|
||||
}
|
||||
|
||||
this._headers = (headers instanceof HttpHeaders ? headers : new HttpHeaders(headers));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the HTTP method that this request will use.
|
||||
*/
|
||||
public get httpMethod(): HttpMethod {
|
||||
return this._httpMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the URL that this request will be sent to.
|
||||
*/
|
||||
public get url(): string {
|
||||
return this._url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the HTTP headers that will be sent with this request.
|
||||
*/
|
||||
public get headers(): HttpHeaders {
|
||||
return this._headers;
|
||||
}
|
||||
public readonly headers: HttpHeaders;
|
||||
|
||||
/**
|
||||
* Get the body that will be sent with this request.
|
||||
*
|
||||
* @param httpMethod The HTTP method that this request will use.
|
||||
* @param url The URL that this request will be sent to.
|
||||
* @param headers The HTTP headers that will be sent with this request.
|
||||
* @param body The body that will be sent with this request.
|
||||
*/
|
||||
public get body(): string | undefined {
|
||||
return this._body;
|
||||
constructor(public httpMethod: HttpMethod, public url: string, headers: HttpHeaders | RawHttpHeaders, public body?: string) {
|
||||
if (!this.url) {
|
||||
const urlString: string = (this.url === undefined || this.url === null ? this.url : `"${this.url}"`);
|
||||
throw new Error(`${urlString} is not a valid URL for a HttpRequest.`);
|
||||
}
|
||||
|
||||
this.headers = (headers instanceof HttpHeaders ? headers : new HttpHeaders(headers));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a deep clone/copy of this HttpRequest.
|
||||
*/
|
||||
public clone(): HttpRequest {
|
||||
return JSON.parse(JSON.stringify(this));
|
||||
return new HttpRequest(this.httpMethod, this.url, this.headers.clone(), this.body);
|
||||
}
|
||||
}
|
|
@ -42,6 +42,10 @@ export interface RetryOptions {
|
|||
* The maximum number of milliseconds to wait before retrying.
|
||||
*/
|
||||
maximumRetryIntervalInMilliseconds?: number;
|
||||
/**
|
||||
* The function to use to delay before sending a retry attempt.
|
||||
*/
|
||||
delayFunction?: (delayInMilliseconds: number) => Promise<void>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -49,33 +53,35 @@ export interface RetryOptions {
|
|||
*/
|
||||
export function exponentialRetryPolicy(retryOptions?: RetryOptions): RequestPolicyFactory {
|
||||
return (nextPolicy: RequestPolicy, options: RequestPolicyOptions) => {
|
||||
return new ExponentialRetryPolicy(retryOptions || {}, nextPolicy, options, utils.delay);
|
||||
return new ExponentialRetryPolicy(retryOptions || {}, nextPolicy, options);
|
||||
};
|
||||
}
|
||||
|
||||
class ExponentialRetryPolicy extends BaseRequestPolicy {
|
||||
private readonly maximumAttempts: number;
|
||||
private readonly initialRetryDelayInMilliseconds: number;
|
||||
private readonly maximumRetryDelayInMilliseconds: number;
|
||||
private readonly _maximumAttempts: number;
|
||||
private readonly _initialRetryDelayInMilliseconds: number;
|
||||
private readonly _maximumRetryDelayInMilliseconds: number;
|
||||
private readonly _delayFunction: (delayInMilliseconds: number) => Promise<void>;
|
||||
|
||||
constructor(retryOptions: RetryOptions, nextPolicy: RequestPolicy, options: RequestPolicyOptions, private readonly delayFunction: (delay: number) => Promise<never>) {
|
||||
constructor(retryOptions: RetryOptions, nextPolicy: RequestPolicy, options: RequestPolicyOptions) {
|
||||
super(nextPolicy, options);
|
||||
|
||||
this.maximumAttempts = retryOptions.maximumAttempts || 3;
|
||||
this.initialRetryDelayInMilliseconds = retryOptions.initialRetryDelayInMilliseconds || 30 * 1000;
|
||||
this.maximumRetryDelayInMilliseconds = retryOptions.maximumRetryIntervalInMilliseconds || 90 * 1000;
|
||||
this._maximumAttempts = retryOptions.maximumAttempts || 3;
|
||||
this._initialRetryDelayInMilliseconds = retryOptions.initialRetryDelayInMilliseconds || 30 * 1000;
|
||||
this._maximumRetryDelayInMilliseconds = retryOptions.maximumRetryIntervalInMilliseconds || 90 * 1000;
|
||||
this._delayFunction = retryOptions.delayFunction || utils.delay;
|
||||
}
|
||||
|
||||
public async send(request: HttpRequest): Promise<HttpResponse> {
|
||||
let response: HttpResponse | undefined;
|
||||
let shouldAttempt: boolean = true;
|
||||
let attemptNumber: number = 0;
|
||||
let attemptDelayInMilliseconds: number = this.initialRetryDelayInMilliseconds;
|
||||
let shouldAttempt = true;
|
||||
let attemptNumber = 0;
|
||||
let attemptDelayInMilliseconds: number = this._initialRetryDelayInMilliseconds;
|
||||
let responseError: RetryError | undefined;
|
||||
while (shouldAttempt) {
|
||||
try {
|
||||
++attemptNumber;
|
||||
response = await this.nextPolicy.send(request.clone());
|
||||
response = await this._nextPolicy.send(request.clone());
|
||||
|
||||
if (response) {
|
||||
const statusCode: number = response.statusCode;
|
||||
|
@ -91,17 +97,17 @@ class ExponentialRetryPolicy extends BaseRequestPolicy {
|
|||
responseError = error;
|
||||
}
|
||||
|
||||
shouldAttempt = shouldAttempt && attemptNumber < this.maximumAttempts;
|
||||
shouldAttempt = shouldAttempt && attemptNumber < this._maximumAttempts;
|
||||
if (shouldAttempt) {
|
||||
response = undefined;
|
||||
|
||||
if (attemptNumber >= 2) {
|
||||
const boundedRandomDelta: number = (attemptDelayInMilliseconds * 0.8) + Math.floor(Math.random() * attemptDelayInMilliseconds * 0.4);
|
||||
const incrementDelta: number = (Math.pow(2, attemptNumber) - 1) * boundedRandomDelta;
|
||||
attemptDelayInMilliseconds = Math.min(attemptDelayInMilliseconds + incrementDelta, this.maximumRetryDelayInMilliseconds);
|
||||
attemptDelayInMilliseconds = Math.min(attemptDelayInMilliseconds + incrementDelta, this._maximumRetryDelayInMilliseconds);
|
||||
}
|
||||
|
||||
await this.delayFunction(attemptDelayInMilliseconds);
|
||||
await this._delayFunction(attemptDelayInMilliseconds);
|
||||
}
|
||||
}
|
||||
return response ? Promise.resolve(response) : Promise.reject(responseError);
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
import * as assert from "assert";
|
||||
import { HttpMethod } from "../../lib/httpMethod";
|
||||
import { HttpRequest } from "../../lib/httpRequest";
|
||||
import { HttpResponse } from "../../lib/httpResponse";
|
||||
import { exponentialRetryPolicy } from "../../lib/policies/exponentialRetryPolicy";
|
||||
import { RequestPolicy } from "../../lib/requestPolicy";
|
||||
import { RequestPolicyFactory } from "../../lib/requestPolicyFactory";
|
||||
import { RequestPolicyOptions } from "../../lib/requestPolicyOptions";
|
||||
import { InMemoryHttpResponse } from "../inMemoryHttpResponse";
|
||||
|
||||
describe("exponentialRetryPolicy", () => {
|
||||
it("should do nothing if no error occurs", async () => {
|
||||
const policyFactory: RequestPolicyFactory = exponentialRetryPolicy({
|
||||
maximumAttempts: 3,
|
||||
initialRetryDelayInMilliseconds: 100,
|
||||
maximumRetryIntervalInMilliseconds: 1000
|
||||
});
|
||||
|
||||
const nextPolicy: RequestPolicy = {
|
||||
send: (request: HttpRequest) => {
|
||||
request.headers.set("A", "B");
|
||||
return Promise.resolve(new InMemoryHttpResponse(request, 200, {}));
|
||||
}
|
||||
}
|
||||
|
||||
const policy: RequestPolicy = policyFactory(nextPolicy, new RequestPolicyOptions());
|
||||
const request = new HttpRequest(HttpMethod.GET, "https://spam.com", {});
|
||||
const response: HttpResponse = await policy.send(request);
|
||||
|
||||
assert.deepStrictEqual(request, new HttpRequest(HttpMethod.GET, "https://spam.com", {}), "The original request should not be modified.");
|
||||
assert.deepStrictEqual(response.request, new HttpRequest(HttpMethod.GET, "https://spam.com", { "A": "B" }), "The request associated with the response should have the modified header.");
|
||||
});
|
||||
|
||||
it("should retry if an undefined HttpResponse is returned", async () => {
|
||||
let millisecondsDelayed: number = 0;
|
||||
|
||||
const policyFactory: RequestPolicyFactory = exponentialRetryPolicy({
|
||||
maximumAttempts: 3,
|
||||
initialRetryDelayInMilliseconds: 30 * 1000,
|
||||
maximumRetryIntervalInMilliseconds: 90 * 1000,
|
||||
delayFunction: (delayInMilliseconds: number) => {
|
||||
millisecondsDelayed += delayInMilliseconds;
|
||||
return Promise.resolve();
|
||||
}
|
||||
});
|
||||
|
||||
let attempt = 0;
|
||||
|
||||
const nextPolicy: RequestPolicy = {
|
||||
send: (request: HttpRequest) => {
|
||||
++attempt;
|
||||
request.headers.set("A", attempt);
|
||||
return Promise.resolve(attempt === 1 ? <any>undefined : new InMemoryHttpResponse(request, 200, {}));
|
||||
}
|
||||
}
|
||||
|
||||
const policy: RequestPolicy = policyFactory(nextPolicy, new RequestPolicyOptions());
|
||||
const request = new HttpRequest(HttpMethod.GET, "https://spam.com", {});
|
||||
const response: HttpResponse = await policy.send(request);
|
||||
|
||||
assert.deepStrictEqual(request, new HttpRequest(HttpMethod.GET, "https://spam.com", {}), "The original request should not be modified.");
|
||||
assert.deepStrictEqual(response.request, new HttpRequest(HttpMethod.GET, "https://spam.com", { "A": "2" }), "The request associated with the response should have the modified header.");
|
||||
assert.strictEqual(millisecondsDelayed, 30 * 1000);
|
||||
});
|
||||
});
|
|
@ -37,9 +37,13 @@ export declare class HttpHeaders {
|
|||
*/
|
||||
get(headerName: string): string | undefined;
|
||||
/**
|
||||
* Get the headers that are contained in this collection.
|
||||
* Get the headers that are contained this collection as an object.
|
||||
*/
|
||||
headers(): HttpHeader[];
|
||||
rawHeaders(): RawHttpHeaders;
|
||||
/**
|
||||
* Get the headers that are contained in this collection as an array.
|
||||
*/
|
||||
headersArray(): HttpHeader[];
|
||||
/**
|
||||
* Get the header names that are contained in this collection.
|
||||
*/
|
||||
|
@ -52,4 +56,8 @@ export declare class HttpHeaders {
|
|||
* Get the JSON object representation of this HTTP header collection.
|
||||
*/
|
||||
toJson(): RawHttpHeaders;
|
||||
/**
|
||||
* Create a deep clone/copy of this HttpHeaders collection.
|
||||
*/
|
||||
clone(): HttpHeaders;
|
||||
}
|
||||
|
|
|
@ -4,27 +4,21 @@ import { HttpMethod } from "./httpMethod";
|
|||
* An individual HTTP request that can be sent with a HttpClient.
|
||||
*/
|
||||
export declare class HttpRequest {
|
||||
private _httpMethod;
|
||||
private _url;
|
||||
private _body;
|
||||
private readonly _headers;
|
||||
constructor(_httpMethod: HttpMethod, _url: string, headers: HttpHeaders | RawHttpHeaders, _body?: string | undefined);
|
||||
/**
|
||||
* Get the HTTP method that this request will use.
|
||||
*/
|
||||
readonly httpMethod: HttpMethod;
|
||||
/**
|
||||
* Get the URL that this request will be sent to.
|
||||
*/
|
||||
readonly url: string;
|
||||
httpMethod: HttpMethod;
|
||||
url: string;
|
||||
body: string | undefined;
|
||||
/**
|
||||
* Get the HTTP headers that will be sent with this request.
|
||||
*/
|
||||
readonly headers: HttpHeaders;
|
||||
/**
|
||||
* Get the body that will be sent with this request.
|
||||
*
|
||||
* @param httpMethod The HTTP method that this request will use.
|
||||
* @param url The URL that this request will be sent to.
|
||||
* @param headers The HTTP headers that will be sent with this request.
|
||||
* @param body The body that will be sent with this request.
|
||||
*/
|
||||
readonly body: string | undefined;
|
||||
constructor(httpMethod: HttpMethod, url: string, headers: HttpHeaders | RawHttpHeaders, body?: string | undefined);
|
||||
/**
|
||||
* Create a deep clone/copy of this HttpRequest.
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
import { RequestPolicyFactory } from "../requestPolicyFactory";
|
||||
/**
|
||||
* An error that can be thrown when the maximum number of attempts have been attempted.
|
||||
*/
|
||||
export interface RetryError extends Error {
|
||||
/**
|
||||
* The message that describes the retry failure.
|
||||
*/
|
||||
message: string;
|
||||
/**
|
||||
* The error code that describes the retry failure.
|
||||
*/
|
||||
code?: string;
|
||||
/**
|
||||
* An inner error that this RetryError wraps.
|
||||
*/
|
||||
innerError?: RetryError;
|
||||
}
|
||||
/**
|
||||
* The options that can be passed to an ExponentialRetryPolicy.
|
||||
*/
|
||||
export interface RetryOptions {
|
||||
/**
|
||||
* The maximum number of attempts that the retry policy will perform before failing. The first
|
||||
* attempt after a failure is considered the 2nd attempt.
|
||||
*/
|
||||
maximumAttempts?: number;
|
||||
/**
|
||||
* The number of milliseconds to delay before attempting again.
|
||||
*/
|
||||
initialRetryDelayInMilliseconds?: number;
|
||||
/**
|
||||
* The maximum number of milliseconds to wait before retrying.
|
||||
*/
|
||||
maximumRetryIntervalInMilliseconds?: number;
|
||||
/**
|
||||
* The function to use to delay before sending a retry attempt.
|
||||
*/
|
||||
delayFunction?: (delayInMilliseconds: number) => Promise<void>;
|
||||
}
|
||||
/**
|
||||
* Get a RequestPolicyFactory that creates ExponentialRetryPolicies.
|
||||
*/
|
||||
export declare function exponentialRetryPolicy(retryOptions?: RetryOptions): RequestPolicyFactory;
|
|
@ -1,6 +1,6 @@
|
|||
import { RequestPolicyFactory } from "../requestPolicyFactory";
|
||||
/**
|
||||
* Get a RequestPolicyFactory that creates UserAgentRequestPolicies.
|
||||
* Get a RequestPolicyFactory that creates UserAgentPolicies.
|
||||
* @param userAgent The userAgent string to apply to each outgoing request.
|
||||
*/
|
||||
export declare function userAgentPolicy(userAgent: string): RequestPolicyFactory;
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
export {};
|
Загрузка…
Ссылка в новой задаче