UNPKG

mappersmith

Version:

It is a lightweight rest client for node.js and the browser

1 lines 9.55 kB
{"version":3,"sources":["../../../../../src/middleware/retry/v2/index.ts"],"sourcesContent":["import type { Middleware, ResponseGetter } from '../../index'\nimport { configs } from '../../../index'\nimport { assign } from '../../../utils/index'\nimport { Response } from '../../../response'\nimport type { Request } from '../../../request'\n\nexport interface RetryMiddlewareOptions {\n readonly headerRetryCount: string\n readonly headerRetryTime: string\n readonly maxRetryTimeInSecs: number\n readonly initialRetryTimeInSecs: number\n readonly factor: number\n readonly multiplier: number\n readonly retries: number\n validateRetry(response: Response): boolean\n}\n\nexport const defaultRetryConfigs: RetryMiddlewareOptions = {\n headerRetryCount: 'X-Mappersmith-Retry-Count',\n headerRetryTime: 'X-Mappersmith-Retry-Time',\n maxRetryTimeInSecs: 5,\n initialRetryTimeInSecs: 0.1,\n factor: 0.2, // randomization factor\n multiplier: 2, // exponential factor\n retries: 5, // max retries\n validateRetry: (response: Response) => response.responseStatus >= 500, // a function that returns true if the request should be retried\n}\n\ntype RetryMiddlewareType = Middleware<{\n enableRetry: boolean\n inboundRequest: Request\n}>\n\n/**\n * This middleware will automatically retry GET requests up to the configured amount of\n * retries using a randomization function that grows exponentially. The retry count and\n * the time used will be included as a header in the response.\n *\n * The retry time is calculated using the following formula:\n * retryTime = min(\n * random(previousRetryTime - randomizedFactor, previousRetryTime + randomizedFactor) * multipler,\n * maxRetryTime\n * )\n *\n * Take a look at `calculateExponentialRetryTime` for more information.\n *\n * @param {Object} retryConfigs\n * @param {String} retryConfigs.headerRetryCount (default: 'X-Mappersmith-Retry-Count')\n * @param {String} retryConfigs.headerRetryTime (default: 'X-Mappersmith-Retry-Time')\n * @param {Number} retryConfigs.maxRetryTimeInSecs (default: 5)\n * @param {Number} retryConfigs.initialRetryTimeInSecs (default: 1)\n * @param {Number} retryConfigs.factor (default: 0.2) - randomization factor\n * @param {Number} retryConfigs.multiplier (default: 2) - exponential factor\n * @param {Number} retryConfigs.retries (default: 5) - max retries\n */\nexport const RetryMiddleware = (\n customConfigs: Partial<RetryMiddlewareOptions> = {}\n): RetryMiddlewareType =>\n function RetryMiddleware() {\n return {\n request(request) {\n this.enableRetry = request.method() === 'get'\n this.inboundRequest = request\n return request\n },\n\n response(next) {\n const retryConfigs = assign({}, defaultRetryConfigs, customConfigs)\n const inboundRequest = this.inboundRequest\n\n if (!this.enableRetry) {\n return next()\n }\n\n if (!configs.Promise) {\n return next()\n }\n\n if (!inboundRequest) {\n return next()\n }\n\n return new configs.Promise((resolve, reject) => {\n const retryTime = retryConfigs.initialRetryTimeInSecs * 1000\n retriableRequest(\n resolve,\n reject,\n next,\n inboundRequest\n )(randomFromRetryTime(retryTime, retryConfigs.factor), 0, retryConfigs)\n })\n },\n }\n }\n\nexport default RetryMiddleware\n\ntype RetryFn = (retryTime: number, retryCount: number, retryConfigs: RetryMiddlewareOptions) => void\ntype RetriableRequestFn = (\n resolve: (value: Response | PromiseLike<Response>) => void,\n reject: (reason?: unknown) => void,\n next: ResponseGetter,\n response: Request\n) => RetryFn\nconst retriableRequest: RetriableRequestFn = (resolve, reject, next, request) => {\n const retry: RetryFn = (retryTime, retryCount, retryConfigs) => {\n const nextRetryTime = calculateExponentialRetryTime(retryTime, retryConfigs)\n const shouldRetry = retryCount < retryConfigs.retries\n const scheduleRequest = () => {\n setTimeout(() => retry(nextRetryTime, retryCount + 1, retryConfigs), retryTime)\n }\n\n next()\n .then((response) => {\n if (shouldRetry && retryConfigs.validateRetry(response)) {\n scheduleRequest()\n } else {\n try {\n resolve(\n enhancedResponse(\n response,\n retryConfigs.headerRetryCount,\n retryCount,\n retryConfigs.headerRetryTime,\n retryTime\n )\n )\n } catch (e) {\n let errorMessage = ''\n if (response instanceof Error) {\n errorMessage = response.message\n }\n if (typeof e === 'object' && e !== null && 'message' in e) {\n errorMessage = (e as Record<'message', string>).message\n }\n reject(new Response(request, 400, errorMessage, {}, [new Error(errorMessage)]))\n }\n }\n })\n .catch((response) => {\n if (shouldRetry && retryConfigs.validateRetry(response)) {\n scheduleRequest()\n } else {\n try {\n reject(\n enhancedResponse(\n response,\n retryConfigs.headerRetryCount,\n retryCount,\n retryConfigs.headerRetryTime,\n retryTime\n )\n )\n } catch (e) {\n let errorMessage = ''\n if (response instanceof Error) {\n errorMessage = response.message\n }\n if (typeof e === 'object' && e !== null && 'message' in e) {\n errorMessage = (e as Record<'message', string>).message\n }\n reject(new Response(request, 400, errorMessage, {}, [response]))\n }\n }\n })\n }\n\n return retry\n}\n\n/**\n * Increases the retry time for each attempt using a randomization function that grows exponentially.\n * The value is limited by `retryConfigs.maxRetryTimeInSecs`.\n * @param {Number} retryTime\n *\n * @return {Number}\n */\nexport const calculateExponentialRetryTime = (\n retryTime: number,\n retryConfigs: RetryMiddlewareOptions\n) =>\n Math.min(\n randomFromRetryTime(retryTime, retryConfigs.factor) * retryConfigs.multiplier,\n retryConfigs.maxRetryTimeInSecs * 1000\n )\n\nconst randomFromRetryTime = (retryTime: number, factor: number) => {\n const delta = factor * retryTime\n return random(retryTime - delta, retryTime + delta)\n}\n\nconst random = (min: number, max: number) => {\n return Math.random() * (max - min) + min\n}\n\nconst enhancedResponse = (\n response: Response,\n headerRetryCount: string,\n retryCount: number,\n headerRetryTime: string,\n retryTime: number\n) =>\n response.enhance({\n headers: {\n [headerRetryCount]: retryCount,\n [headerRetryTime]: retryTime,\n },\n })\n"],"mappings":"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","names":["RetryMiddleware"]}