@softchef/cdk-iot-device-management
Version:
IoT device management is composed of things, thing types, thing groups, jobs, files API services. The constructs can be used independently, that are based on full-managed service to create an API Gateway & Lambda function.
131 lines (130 loc) • 7.29 kB
JavaScript
import { __awaiter, __generator } from "tslib";
import { HttpRequest } from "@aws-sdk/protocol-http";
import { isThrottlingError } from "@aws-sdk/service-error-classification";
import { v4 } from "uuid";
import { DEFAULT_MAX_ATTEMPTS, RETRY_MODES } from "./config";
import { DEFAULT_RETRY_DELAY_BASE, INITIAL_RETRY_TOKENS, INVOCATION_ID_HEADER, REQUEST_HEADER, THROTTLING_RETRY_DELAY_BASE, } from "./constants";
import { getDefaultRetryQuota } from "./defaultRetryQuota";
import { defaultDelayDecider } from "./delayDecider";
import { defaultRetryDecider } from "./retryDecider";
var StandardRetryStrategy = (function () {
function StandardRetryStrategy(maxAttemptsProvider, options) {
var _a, _b, _c;
this.maxAttemptsProvider = maxAttemptsProvider;
this.mode = RETRY_MODES.STANDARD;
this.retryDecider = (_a = options === null || options === void 0 ? void 0 : options.retryDecider) !== null && _a !== void 0 ? _a : defaultRetryDecider;
this.delayDecider = (_b = options === null || options === void 0 ? void 0 : options.delayDecider) !== null && _b !== void 0 ? _b : defaultDelayDecider;
this.retryQuota = (_c = options === null || options === void 0 ? void 0 : options.retryQuota) !== null && _c !== void 0 ? _c : getDefaultRetryQuota(INITIAL_RETRY_TOKENS);
}
StandardRetryStrategy.prototype.shouldRetry = function (error, attempts, maxAttempts) {
return attempts < maxAttempts && this.retryDecider(error) && this.retryQuota.hasRetryTokens(error);
};
StandardRetryStrategy.prototype.getMaxAttempts = function () {
return __awaiter(this, void 0, void 0, function () {
var maxAttempts, error_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 2, , 3]);
return [4, this.maxAttemptsProvider()];
case 1:
maxAttempts = _a.sent();
return [3, 3];
case 2:
error_1 = _a.sent();
maxAttempts = DEFAULT_MAX_ATTEMPTS;
return [3, 3];
case 3: return [2, maxAttempts];
}
});
});
};
StandardRetryStrategy.prototype.retry = function (next, args, options) {
return __awaiter(this, void 0, void 0, function () {
var retryTokenAmount, attempts, totalDelay, maxAttempts, request, _loop_1, this_1, state_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
attempts = 0;
totalDelay = 0;
return [4, this.getMaxAttempts()];
case 1:
maxAttempts = _a.sent();
request = args.request;
if (HttpRequest.isInstance(request)) {
request.headers[INVOCATION_ID_HEADER] = v4();
}
_loop_1 = function () {
var _b, response, output, e_1, err, delay_1;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
_c.trys.push([0, 4, , 7]);
if (HttpRequest.isInstance(request)) {
request.headers[REQUEST_HEADER] = "attempt=" + (attempts + 1) + "; max=" + maxAttempts;
}
if (!(options === null || options === void 0 ? void 0 : options.beforeRequest)) return [3, 2];
return [4, options.beforeRequest()];
case 1:
_c.sent();
_c.label = 2;
case 2: return [4, next(args)];
case 3:
_b = _c.sent(), response = _b.response, output = _b.output;
if (options === null || options === void 0 ? void 0 : options.afterRequest) {
options.afterRequest(response);
}
this_1.retryQuota.releaseRetryTokens(retryTokenAmount);
output.$metadata.attempts = attempts + 1;
output.$metadata.totalRetryDelay = totalDelay;
return [2, { value: { response: response, output: output } }];
case 4:
e_1 = _c.sent();
err = asSdkError(e_1);
attempts++;
if (!this_1.shouldRetry(err, attempts, maxAttempts)) return [3, 6];
retryTokenAmount = this_1.retryQuota.retrieveRetryTokens(err);
delay_1 = this_1.delayDecider(isThrottlingError(err) ? THROTTLING_RETRY_DELAY_BASE : DEFAULT_RETRY_DELAY_BASE, attempts);
totalDelay += delay_1;
return [4, new Promise(function (resolve) { return setTimeout(resolve, delay_1); })];
case 5:
_c.sent();
return [2, "continue"];
case 6:
if (!err.$metadata) {
err.$metadata = {};
}
err.$metadata.attempts = attempts;
err.$metadata.totalRetryDelay = totalDelay;
throw err;
case 7: return [2];
}
});
};
this_1 = this;
_a.label = 2;
case 2:
if (!true) return [3, 4];
return [5, _loop_1()];
case 3:
state_1 = _a.sent();
if (typeof state_1 === "object")
return [2, state_1.value];
return [3, 2];
case 4: return [2];
}
});
});
};
return StandardRetryStrategy;
}());
export { StandardRetryStrategy };
var asSdkError = function (error) {
if (error instanceof Error)
return error;
if (error instanceof Object)
return Object.assign(new Error(), error);
if (typeof error === "string")
return new Error(error);
return new Error("AWS SDK error wrapper for " + error);
};