UNPKG

unstructured-client

Version:

<h3 align="center"> <img src="https://raw.githubusercontent.com/Unstructured-IO/unstructured/main/img/unstructured_logo.png" height="200" > </h3>

153 lines 5.06 kB
"use strict"; /* * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.retry = exports.TemporaryError = exports.PermanentError = void 0; const http_js_1 = require("./http.js"); const defaultBackoff = { initialInterval: 500, maxInterval: 60000, exponent: 1.5, maxElapsedTime: 3600000, }; /** * PermanentError is an error that is not recoverable. Throwing this error will * cause a retry loop to terminate. */ class PermanentError extends Error { constructor(message, options) { let msg = message; if (options?.cause) { msg += `: ${options.cause}`; } super(msg, options); this.name = "PermanentError"; // In older runtimes, the cause field would not have been assigned through // the super() call. if (typeof this.cause === "undefined") { this.cause = options?.cause; } Object.setPrototypeOf(this, PermanentError.prototype); } } exports.PermanentError = PermanentError; /** * TemporaryError is an error is used to signal that an HTTP request can be * retried as part of a retry loop. If retry attempts are exhausted and this * error is thrown, the response will be returned to the caller. */ class TemporaryError extends Error { constructor(message, response) { super(message); this.response = response; this.name = "TemporaryError"; Object.setPrototypeOf(this, TemporaryError.prototype); } } exports.TemporaryError = TemporaryError; async function retry(fetchFn, options) { switch (options.config.strategy) { case "backoff": return retryBackoff(wrapFetcher(fetchFn, { statusCodes: options.statusCodes, retryConnectionErrors: !!options.config.retryConnectionErrors, }), options.config.backoff ?? defaultBackoff); default: return await fetchFn(); } } exports.retry = retry; function wrapFetcher(fn, options) { return async () => { try { const res = await fn(); if (isRetryableResponse(res, options.statusCodes)) { throw new TemporaryError("Response failed with retryable status code", res); } return res; } catch (err) { if (err instanceof TemporaryError) { throw err; } if (options.retryConnectionErrors && ((0, http_js_1.isTimeoutError)(err) || (0, http_js_1.isConnectionError)(err))) { throw err; } throw new PermanentError("Permanent error", { cause: err }); } }; } const codeRangeRE = new RegExp("^[0-9]xx$", "i"); function isRetryableResponse(res, statusCodes) { const actual = `${res.status}`; return statusCodes.some((code) => { if (!codeRangeRE.test(code)) { return code === actual; } const expectFamily = code.charAt(0); if (!expectFamily) { throw new Error("Invalid status code range"); } const actualFamily = actual.charAt(0); if (!actualFamily) { throw new Error(`Invalid response status code: ${actual}`); } return actualFamily === expectFamily; }); } async function retryBackoff(fn, strategy) { const { maxElapsedTime, initialInterval, exponent, maxInterval } = strategy; const start = Date.now(); let x = 0; while (true) { try { const res = await fn(); return res; } catch (err) { if (err instanceof PermanentError) { throw err.cause; } const elapsed = Date.now() - start; if (elapsed > maxElapsedTime) { if (err instanceof TemporaryError) { return err.response; } throw err; } let retryInterval = 0; if (err instanceof TemporaryError) { retryInterval = retryIntervalFromResponse(err.response); } if (retryInterval <= 0) { retryInterval = initialInterval * Math.pow(x, exponent) + Math.random() * 1000; } const d = Math.min(retryInterval, maxInterval); await delay(d); x++; } } } function retryIntervalFromResponse(res) { const retryVal = res.headers.get("retry-after") || ""; if (!retryVal) { return 0; } const parsedNumber = Number(retryVal); if (Number.isInteger(parsedNumber)) { return parsedNumber * 1000; } const parsedDate = Date.parse(retryVal); if (Number.isInteger(parsedDate)) { const deltaMS = parsedDate - Date.now(); return deltaMS > 0 ? Math.ceil(deltaMS) : 0; } return 0; } async function delay(delay) { return new Promise((resolve) => setTimeout(resolve, delay)); } //# sourceMappingURL=retries.js.map