Stubs for adding throttle support.
This commit is contained in:
parent
abab9f6aa2
commit
2f0e679f0b
@ -16,6 +16,7 @@ export type ConnectionInfo = {
|
|||||||
user?: string,
|
user?: string,
|
||||||
password?: string,
|
password?: string,
|
||||||
allowInsecureAuthentication?: boolean,
|
allowInsecureAuthentication?: boolean,
|
||||||
|
throttleLimit?: number,
|
||||||
timeout?: number,
|
timeout?: number,
|
||||||
headers?: { [key: string]: string | number }
|
headers?: { [key: string]: string | number }
|
||||||
};
|
};
|
||||||
@ -42,6 +43,24 @@ export type FetchJsonResponse = {
|
|||||||
|
|
||||||
type Header = { key: string, value: string };
|
type Header = { key: string, value: string };
|
||||||
|
|
||||||
|
function getResponse(response: Response): FetchJsonResponse {
|
||||||
|
const headers: { [ header: string ]: string } = { };
|
||||||
|
if (response.headers.forEach) {
|
||||||
|
response.headers.forEach((value, key) => {
|
||||||
|
headers[key.toLowerCase()] = value;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
(<() => Array<string>>((<any>(response.headers)).keys))().forEach((key) => {
|
||||||
|
headers[key.toLowerCase()] = response.headers.get(key);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
statusCode: response.status,
|
||||||
|
status: response.statusText,
|
||||||
|
headers: headers
|
||||||
|
};
|
||||||
|
}
|
||||||
export function fetchJson(connection: string | ConnectionInfo, json?: string, processFunc?: (value: any, response: FetchJsonResponse) => any): Promise<any> {
|
export function fetchJson(connection: string | ConnectionInfo, json?: string, processFunc?: (value: any, response: FetchJsonResponse) => any): Promise<any> {
|
||||||
const headers: { [key: string]: Header } = { };
|
const headers: { [key: string]: Header } = { };
|
||||||
|
|
||||||
@ -60,6 +79,8 @@ export function fetchJson(connection: string | ConnectionInfo, json?: string, pr
|
|||||||
let allow304 = false;
|
let allow304 = false;
|
||||||
|
|
||||||
let timeout = 2 * 60 * 1000;
|
let timeout = 2 * 60 * 1000;
|
||||||
|
let throttle = 25;
|
||||||
|
if (options.throttleLimit) { throttle = options.throttleLimit; }
|
||||||
|
|
||||||
if (typeof(connection) === "string") {
|
if (typeof(connection) === "string") {
|
||||||
url = connection;
|
url = connection;
|
||||||
@ -101,103 +122,105 @@ export function fetchJson(connection: string | ConnectionInfo, json?: string, pr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Promise(function(resolve, reject) {
|
if (json) {
|
||||||
|
options.method = "POST";
|
||||||
|
options.body = json;
|
||||||
|
headers["content-type"] = { key: "Content-Type", value: "application/json" };
|
||||||
|
}
|
||||||
|
|
||||||
|
const flatHeaders: { [ key: string ]: string } = { };
|
||||||
|
Object.keys(headers).forEach((key) => {
|
||||||
|
const header = headers[key];
|
||||||
|
flatHeaders[header.key] = header.value;
|
||||||
|
});
|
||||||
|
options.headers = flatHeaders;
|
||||||
|
|
||||||
|
const runningTimeout = (function() {
|
||||||
let timer: any = null;
|
let timer: any = null;
|
||||||
if (timeout) {
|
const promise = new Promise(function(resolve, reject) {
|
||||||
timer = setTimeout(() => {
|
if (timeout) {
|
||||||
if (timer == null) { return; }
|
timer = setTimeout(() => {
|
||||||
timer = null;
|
if (timer == null) { return; }
|
||||||
|
timer = null;
|
||||||
|
|
||||||
reject(logger.makeError("timeout", Logger.errors.TIMEOUT, { timeout: timeout }));
|
reject(logger.makeError("timeout", Logger.errors.TIMEOUT, { timeout: timeout }));
|
||||||
}, timeout);
|
}, timeout);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const cancelTimeout = () => {
|
const cancel = function() {
|
||||||
if (timer == null) { return; }
|
if (timer == null) { return; }
|
||||||
clearTimeout(timer);
|
clearTimeout(timer);
|
||||||
timer = null;
|
timer = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (json) {
|
return { promise, cancel };
|
||||||
options.method = "POST";
|
})();
|
||||||
options.body = json;
|
if (throttle == 100) {
|
||||||
headers["content-type"] = { key: "Content-Type", value: "application/json" };
|
console.log(throttle);
|
||||||
|
}
|
||||||
|
|
||||||
|
const runningFetch = (async function() {
|
||||||
|
|
||||||
|
let response: Response = null;
|
||||||
|
let body: string = null;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
response = await fetch(url, options);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
body = await response.text();
|
||||||
|
|
||||||
|
if (allow304 && response.status === 304) {
|
||||||
|
// Leave body as null
|
||||||
|
break;
|
||||||
|
|
||||||
|
} else if (!response.ok) {
|
||||||
|
runningTimeout.cancel();
|
||||||
|
logger.throwError("bad response", Logger.errors.SERVER_ERROR, {
|
||||||
|
status: response.status,
|
||||||
|
body: body,
|
||||||
|
type: response.type,
|
||||||
|
url: response.url
|
||||||
|
});
|
||||||
|
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const flatHeaders: { [ key: string ]: string } = { };
|
runningTimeout.cancel();
|
||||||
Object.keys(headers).forEach((key) => {
|
|
||||||
const header = headers[key];
|
|
||||||
flatHeaders[header.key] = header.value;
|
|
||||||
});
|
|
||||||
options.headers = flatHeaders;
|
|
||||||
|
|
||||||
return fetch(url, options).then((response) => {
|
let json: any = null;
|
||||||
return response.text().then((body) => {
|
if (body != null) {
|
||||||
|
try {
|
||||||
|
json = JSON.parse(body);
|
||||||
|
} catch (error) {
|
||||||
|
logger.throwError("invalid JSON", Logger.errors.SERVER_ERROR, {
|
||||||
|
body: body,
|
||||||
|
error: error,
|
||||||
|
url: url
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let json: any = null;
|
if (processFunc) {
|
||||||
|
try {
|
||||||
|
json = await processFunc(json, getResponse(response));
|
||||||
|
} catch (error) {
|
||||||
|
logger.throwError("processing response error", Logger.errors.SERVER_ERROR, {
|
||||||
|
body: json,
|
||||||
|
error: error
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (allow304 && response.status === 304) {
|
return json;
|
||||||
// Leave json as null
|
})();
|
||||||
|
|
||||||
} else if (!response.ok) {
|
return Promise.race([ runningTimeout.promise, runningFetch ]);
|
||||||
logger.throwError("bad response", Logger.errors.SERVER_ERROR, {
|
|
||||||
status: response.status,
|
|
||||||
body: body,
|
|
||||||
type: response.type,
|
|
||||||
url: response.url
|
|
||||||
});
|
|
||||||
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
json = JSON.parse(body);
|
|
||||||
} catch (error) {
|
|
||||||
logger.throwError("invalid JSON", Logger.errors.SERVER_ERROR, {
|
|
||||||
body: body,
|
|
||||||
error: error,
|
|
||||||
url: url
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (processFunc) {
|
|
||||||
try {
|
|
||||||
const headers: { [ header: string ]: string } = { };
|
|
||||||
if (response.headers.forEach) {
|
|
||||||
response.headers.forEach((value, key) => {
|
|
||||||
headers[key.toLowerCase()] = value;
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
(<() => Array<string>>((<any>(response.headers)).keys))().forEach((key) => {
|
|
||||||
headers[key.toLowerCase()] = response.headers.get(key);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
json = processFunc(json, {
|
|
||||||
statusCode: response.status,
|
|
||||||
status: response.statusText,
|
|
||||||
headers: headers
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
logger.throwError("processing response error", Logger.errors.SERVER_ERROR, {
|
|
||||||
body: json,
|
|
||||||
error: error
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return json;
|
|
||||||
});
|
|
||||||
|
|
||||||
}, (error) => {
|
|
||||||
throw error;
|
|
||||||
}).then((result) => {
|
|
||||||
cancelTimeout();
|
|
||||||
resolve(result);
|
|
||||||
}, (error) => {
|
|
||||||
cancelTimeout();
|
|
||||||
reject(error);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function poll(func: () => Promise<any>, options?: PollOptions): Promise<any> {
|
export function poll(func: () => Promise<any>, options?: PollOptions): Promise<any> {
|
||||||
|
Loading…
Reference in New Issue
Block a user