111 lines
4.7 KiB
JavaScript
111 lines
4.7 KiB
JavaScript
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.getRetryAfterHint = exports.getRetryPlugin = exports.retryMiddlewareOptions = exports.retryMiddleware = void 0;
|
|
const protocol_http_1 = require("@smithy/protocol-http");
|
|
const service_error_classification_1 = require("@smithy/service-error-classification");
|
|
const util_retry_1 = require("@smithy/util-retry");
|
|
const uuid_1 = require("uuid");
|
|
const util_1 = require("./util");
|
|
const retryMiddleware = (options) => (next, context) => async (args) => {
|
|
let retryStrategy = await options.retryStrategy();
|
|
const maxAttempts = await options.maxAttempts();
|
|
if (isRetryStrategyV2(retryStrategy)) {
|
|
retryStrategy = retryStrategy;
|
|
let retryToken = await retryStrategy.acquireInitialRetryToken(context["partition_id"]);
|
|
let lastError = new Error();
|
|
let attempts = 0;
|
|
let totalRetryDelay = 0;
|
|
const { request } = args;
|
|
if (protocol_http_1.HttpRequest.isInstance(request)) {
|
|
request.headers[util_retry_1.INVOCATION_ID_HEADER] = (0, uuid_1.v4)();
|
|
}
|
|
while (true) {
|
|
try {
|
|
if (protocol_http_1.HttpRequest.isInstance(request)) {
|
|
request.headers[util_retry_1.REQUEST_HEADER] = `attempt=${attempts + 1}; max=${maxAttempts}`;
|
|
}
|
|
const { response, output } = await next(args);
|
|
retryStrategy.recordSuccess(retryToken);
|
|
output.$metadata.attempts = attempts + 1;
|
|
output.$metadata.totalRetryDelay = totalRetryDelay;
|
|
return { response, output };
|
|
}
|
|
catch (e) {
|
|
const retryErrorInfo = getRetryErrorInfo(e);
|
|
lastError = (0, util_1.asSdkError)(e);
|
|
try {
|
|
retryToken = await retryStrategy.refreshRetryTokenForRetry(retryToken, retryErrorInfo);
|
|
}
|
|
catch (refreshError) {
|
|
if (!lastError.$metadata) {
|
|
lastError.$metadata = {};
|
|
}
|
|
lastError.$metadata.attempts = attempts + 1;
|
|
lastError.$metadata.totalRetryDelay = totalRetryDelay;
|
|
throw lastError;
|
|
}
|
|
attempts = retryToken.getRetryCount();
|
|
const delay = retryToken.getRetryDelay();
|
|
totalRetryDelay += delay;
|
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
retryStrategy = retryStrategy;
|
|
if (retryStrategy === null || retryStrategy === void 0 ? void 0 : retryStrategy.mode)
|
|
context.userAgent = [...(context.userAgent || []), ["cfg/retry-mode", retryStrategy.mode]];
|
|
return retryStrategy.retry(next, args);
|
|
}
|
|
};
|
|
exports.retryMiddleware = retryMiddleware;
|
|
const isRetryStrategyV2 = (retryStrategy) => typeof retryStrategy.acquireInitialRetryToken !== "undefined" &&
|
|
typeof retryStrategy.refreshRetryTokenForRetry !== "undefined" &&
|
|
typeof retryStrategy.recordSuccess !== "undefined";
|
|
const getRetryErrorInfo = (error) => {
|
|
const errorInfo = {
|
|
errorType: getRetryErrorType(error),
|
|
};
|
|
const retryAfterHint = (0, exports.getRetryAfterHint)(error.$response);
|
|
if (retryAfterHint) {
|
|
errorInfo.retryAfterHint = retryAfterHint;
|
|
}
|
|
return errorInfo;
|
|
};
|
|
const getRetryErrorType = (error) => {
|
|
if ((0, service_error_classification_1.isThrottlingError)(error))
|
|
return "THROTTLING";
|
|
if ((0, service_error_classification_1.isTransientError)(error))
|
|
return "TRANSIENT";
|
|
if ((0, service_error_classification_1.isServerError)(error))
|
|
return "SERVER_ERROR";
|
|
return "CLIENT_ERROR";
|
|
};
|
|
exports.retryMiddlewareOptions = {
|
|
name: "retryMiddleware",
|
|
tags: ["RETRY"],
|
|
step: "finalizeRequest",
|
|
priority: "high",
|
|
override: true,
|
|
};
|
|
const getRetryPlugin = (options) => ({
|
|
applyToStack: (clientStack) => {
|
|
clientStack.add((0, exports.retryMiddleware)(options), exports.retryMiddlewareOptions);
|
|
},
|
|
});
|
|
exports.getRetryPlugin = getRetryPlugin;
|
|
const getRetryAfterHint = (response) => {
|
|
if (!protocol_http_1.HttpResponse.isInstance(response))
|
|
return;
|
|
const retryAfterHeaderName = Object.keys(response.headers).find((key) => key.toLowerCase() === "retry-after");
|
|
if (!retryAfterHeaderName)
|
|
return;
|
|
const retryAfter = response.headers[retryAfterHeaderName];
|
|
const retryAfterSeconds = Number(retryAfter);
|
|
if (!Number.isNaN(retryAfterSeconds))
|
|
return new Date(retryAfterSeconds * 1000);
|
|
const retryAfterDate = new Date(retryAfter);
|
|
return retryAfterDate;
|
|
};
|
|
exports.getRetryAfterHint = getRetryAfterHint;
|