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.

171 lines 5.44 kB
/** * @module Resilience */ import {} from "../../../backoff-policies/contracts/_module.js"; import { exponentialBackoff } from "../../../backoff-policies/implementations/_module.js"; import {} from "../../../execution-context/contracts/_module.js"; import {} from "../../../middleware/contracts/_module.js"; import { RetryResilienceError } from "../../../resilience/implementations/resilience.errors.js"; import {} from "../../../time-span/contracts/_module.js"; import { TimeSpan } from "../../../time-span/implementations/_module.js"; import { callInvokable, callErrorPolicyOnValue, delay, callErrorPolicyOnThrow, UnexpectedError, optionSome, optionNone, } from "../../../utilities/_module.js"; /** * @internal */ export function handleOnExecutionAttempt(settings) { const { attempt, args, context, onExecutionAttempt } = settings; void (async () => { try { await callInvokable(onExecutionAttempt, { attempt, args, context, }); } catch (error) { console.error("Error occurred in onExecutionAttempt callback:", error); } })(); } /** * @internal */ export function handleOnRetryDelay(settings) { const { onRetryDelay, error, waitTime, attempt, args, context } = settings; void (async () => { try { await callInvokable(onRetryDelay, { error, waitTime: TimeSpan.fromTimeSpan(waitTime), attempt, args, context, }); } catch (error_) { console.error("Error occurred in onRetryDelay callback:", error_); } })(); } /** * @internal */ async function handleWhenReturn(settings) { const { onExecutionAttempt, attempt, args, context, next, errorPolicy, maxAttempts, backoffPolicy, onRetryDelay, allErrors, } = settings; handleOnExecutionAttempt({ onExecutionAttempt, attempt, args, context, }); const value = await next(); if (!callErrorPolicyOnValue(errorPolicy, value)) { return optionSome(value); } // Handle retrying if an false is returned allErrors.push(value); // Only sleep if there will actually be a next attempt if (attempt < maxAttempts) { const waitTime = callInvokable(backoffPolicy, attempt, value); handleOnRetryDelay({ onRetryDelay, error: value, waitTime, attempt, args, context, }); await delay(waitTime); } return optionNone(); } /** * @internal */ async function handleWhenThrow(settings) { const { error, allErrors, attempt, maxAttempts, backoffPolicy, onRetryDelay, errorPolicy, args, context, } = settings; if (await callErrorPolicyOnThrow(errorPolicy, error)) { allErrors.push(error); } else { throw error; } // Only sleep if there will actually be a next attempt if (attempt < maxAttempts) { const waitTime = callInvokable(backoffPolicy, attempt, error); handleOnRetryDelay({ onRetryDelay, error, waitTime, attempt, args, context, }); await delay(waitTime); } } /** * @internal */ function throwErrors(settings) { const { allErrors, throwLastError, maxAttempts } = settings; if (allErrors.length !== 0 && !throwLastError) { throw RetryResilienceError.create(allErrors, maxAttempts); } if (allErrors.length !== 0 && throwLastError) { throw allErrors.at(-1); } throw new UnexpectedError("retry middleware reached an unreachble state, this is a bug please file issue on github."); } /** * IMPORT_PATH: `@daiso-tech/core/resilience` * @group Middlewares * @throws {RetryResilienceError} */ export function retry(settings = {}) { const { maxAttempts = 4, backoffPolicy = exponentialBackoff(), errorPolicy, onRetryDelay = () => { }, onExecutionAttempt = () => { }, throwLastError = false, } = settings; if (maxAttempts < 1) { throw new TypeError("RetrySettings.maxAttempts cannot be smaller than 1"); } return async ({ args, next, context }) => { const allErrors = []; for (let attempt = 1; attempt <= maxAttempts; attempt++) { try { const result = await handleWhenReturn({ onExecutionAttempt, attempt, args, context, next, errorPolicy, maxAttempts, backoffPolicy, onRetryDelay, allErrors, }); if (result.type === "some") { return result.value; } } catch (error) { await handleWhenThrow({ error, allErrors, attempt, maxAttempts, backoffPolicy, onRetryDelay, errorPolicy, args, context, }); } } return throwErrors({ allErrors, throwLastError, maxAttempts, }); }; } //# sourceMappingURL=retry.js.map