@snap/camera-kit
Version:
Camera Kit Web
62 lines • 3.16 kB
JavaScript
import { __awaiter } from "tslib";
import { copyDefinedProperties } from "../common/copyDefinedProperties";
import { getLogger } from "../logger/logger";
const logger = getLogger("retryingHandler");
const logRetry = (responseOrError, sleep) => {
logger.warn(`Retrying handler got failed response:`, responseOrError, `Waited ${sleep} millis, attempting retry now.`);
};
const sleep = (millis) => new Promise((resolve) => setTimeout(resolve, millis));
const randomInRange = (min, max) => Math.round(Math.random() * (max - min) + min);
const defaultOptions = {
backoffMultiple: 3,
baseSleep: 500,
maxSleep: 5 * 1000,
maxRetries: 10,
retryPredicate: (responseOrError) => (responseOrError instanceof Response ? !responseOrError.ok : true),
};
export function ensureClonedRequest(input) {
return input instanceof Request ? input.clone() : input;
}
export const createRetryingHandler = (options = {}) => {
const definedOptions = copyDefinedProperties(options);
const { backoffMultiple, baseSleep, maxSleep, maxRetries, retryPredicate } = Object.assign(Object.assign({}, defaultOptions), definedOptions);
const jitterSleep = (priorSleep) => __awaiter(void 0, void 0, void 0, function* () {
const nextSleep = Math.min(maxSleep, randomInRange(baseSleep, priorSleep * backoffMultiple));
yield sleep(nextSleep);
return nextSleep;
});
return (next) => (req, metadata) => {
const attemptFn = (priorSleep, retryCount) => (() => __awaiter(void 0, void 0, void 0, function* () {
var _a, _b;
try {
const response = yield next(ensureClonedRequest(req), metadata);
if (retryCount < maxRetries && retryPredicate(response, retryCount)) {
const nextSleep = yield jitterSleep(priorSleep);
if ((_a = metadata === null || metadata === void 0 ? void 0 : metadata.signal) === null || _a === void 0 ? void 0 : _a.aborted)
return response;
logRetry(response, nextSleep);
return attemptFn(nextSleep, retryCount + 1);
}
return response;
}
catch (error) {
if (!(error instanceof Error)) {
throw new Error("Invalid type caught by retrying handler. Handlers may only throw Errors. Got " +
`${JSON.stringify(error)}`);
}
if (error.name === "AbortError")
throw error;
if (retryCount < maxRetries && retryPredicate(error, retryCount)) {
const nextSleep = yield jitterSleep(priorSleep);
if ((_b = metadata === null || metadata === void 0 ? void 0 : metadata.signal) === null || _b === void 0 ? void 0 : _b.aborted)
throw error;
logRetry(error, nextSleep);
return attemptFn(nextSleep, retryCount + 1);
}
throw error;
}
}))();
return attemptFn(baseSleep, 0);
};
};
//# sourceMappingURL=retryingHandler.js.map