UNPKG

@daiso-tech/core

Version:

The library offers flexible, framework-agnostic solutions for modern web applications, built on adaptable components that integrate seamlessly with popular frameworks like Next Js.

79 lines 2.98 kB
/** * @module Async */ import { callInvokable, TimeSpan, } from "../../../utilities/_module-exports.js"; import { exponentialBackoffPolicy, } from "../../../async/backof-policies/_module.js"; import { AbortAsyncError, RetryAsyncError } from "../../../async/async.errors.js"; import { LazyPromise } from "../../../async/utilities/_module.js"; /** * The `retry` middleware enables automatic retries for all errors or specific errors, with configurable backoff policies. * An error will be thrown when all retry attempts fail. * * IMPORT_PATH: `"@daiso-tech/core/async"` * @group Middleware * * @throws {AbortAsyncError} {@link AbortAsyncError} * * @example * ```ts * import { retry } from "@daiso-tech/core/async"; * import { AsyncHooks } from "@daiso-tech/core/utilities"; * * await new AsyncHooks(async (url: string) => { * const response = await fetch(url); * const json = await response.json(); * if (!response.ok) { * throw json * } * return json; * }, retry({ maxAttempts: 8 })).invoke("URL_ENDPOINT"); * ``` */ export function retry(settings = {}) { const { maxAttempts = 4, backoffPolicy = exponentialBackoffPolicy(), retryPolicy = () => true, onRetryStart = () => { }, onRetryEnd = () => { }, onExecutionAttempt = () => { }, } = settings; return async (args, next, context) => { const errors = []; for (let attempt = 1; attempt <= maxAttempts; attempt++) { try { callInvokable(onExecutionAttempt, { attempt, args, context }); return await next(...args); } catch (error) { const time = TimeSpan.fromMilliseconds(callInvokable(backoffPolicy, attempt, error)); callInvokable(onRetryStart, { error, waitTime: time, attempt, args, context, }); errors.push(error); if (error instanceof AbortAsyncError) { throw error; } if (!callInvokable(retryPolicy, error, attempt)) { throw error; } await LazyPromise.delay(time); callInvokable(onRetryEnd, { error, waitTime: time, attempt, args, context, }); } } let errorMessage = `Promise was failed after retried ${String(maxAttempts)} times`; const lastError = errors[errors.length - 1]; if (lastError) { // eslint-disable-next-line @typescript-eslint/no-base-to-string errorMessage = `${errorMessage} and last thrown error was "${String(lastError)}"`; } throw new RetryAsyncError(errorMessage, { errors, maxAttempts, }); }; } //# sourceMappingURL=retry.middleware.js.map