@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.
151 lines • 4.8 kB
JavaScript
/**
* @module Resilience
*/
import {} from "../../../execution-context/contracts/execution-context.contract.js";
import {} from "../../../middleware/contracts/_module.js";
import { RetryIntervalResilienceError } from "../../../resilience/implementations/resilience.errors.js";
import { handleOnExecutionAttempt, handleOnRetryDelay, } from "../../../resilience/implementations/retry/_module.js";
import {} from "../../../time-span/contracts/_module.js";
import { TimeSpan } from "../../../time-span/implementations/_module.js";
import { callErrorPolicyOnThrow, callErrorPolicyOnValue, delay, UnexpectedError, } from "../../../utilities/_module.js";
/**
* @internal
*/
async function handleWhenReturn(settings) {
const { onExecutionAttempt, attempt, args, context, next, errorPolicy, intervalAsTimeSpan, endDate, onRetryDelay, allErrors, } = settings;
handleOnExecutionAttempt({
onExecutionAttempt,
attempt,
args,
context,
});
const value = await next();
if (!callErrorPolicyOnValue(errorPolicy, value)) {
return {
type: "return",
value,
};
}
// Handle retrying if an false is returned
allErrors.push(value);
handleOnRetryDelay({
onRetryDelay,
error: value,
waitTime: intervalAsTimeSpan,
attempt,
args,
context,
});
const remainingAfterValue = endDate.getTime() - Date.now();
if (remainingAfterValue <= 0) {
return {
type: "break",
};
}
await delay(intervalAsTimeSpan);
return {
type: "end",
};
}
/**
* @internal
*/
async function handleWhenThrow(settings) {
const { allErrors, error, errorPolicy, onRetryDelay, intervalAsTimeSpan, attempt, args, context, endDate, } = settings;
if (await callErrorPolicyOnThrow(errorPolicy, error)) {
allErrors.push(error);
}
else {
throw error;
}
handleOnRetryDelay({
onRetryDelay,
error,
waitTime: intervalAsTimeSpan,
attempt,
args,
context,
});
const remainingAfterValue = endDate.getTime() - Date.now();
if (remainingAfterValue <= 0) {
return true;
}
await delay(intervalAsTimeSpan);
return false;
}
/**
* @internal
*/
function throwErrors(settings) {
const { allErrors, throwLastError, attempt, timeAsTimeSpan, intervalAsTimeSpan, } = settings;
if (allErrors.length !== 0 && !throwLastError) {
throw RetryIntervalResilienceError.create(allErrors, attempt - 1, timeAsTimeSpan, intervalAsTimeSpan);
}
if (allErrors.length !== 0 && throwLastError) {
throw allErrors.at(-1);
}
throw new UnexpectedError("retryInterval middleware reached an unreachble state, this is a bug please file issue on github.");
}
/**
* IMPORT_PATH: `"@daiso-tech/core/resilience"`
* @group Middlewares
* @throws {RetryIntervalResilienceError}
*/
export function retryInterval(settings) {
const { time, interval, errorPolicy, onRetryDelay = () => { }, onExecutionAttempt = () => { }, throwLastError = false, } = settings;
const timeAsTimeSpan = TimeSpan.fromTimeSpan(time);
const intervalAsTimeSpan = TimeSpan.fromTimeSpan(interval);
return async ({ args, context, next }) => {
const endDate = timeAsTimeSpan.toEndDate();
const allErrors = [];
let attempt = 1;
while (endDate.getTime() > new Date().getTime()) {
try {
const result = await handleWhenReturn({
onExecutionAttempt,
attempt,
args,
context,
next,
errorPolicy,
intervalAsTimeSpan,
endDate,
onRetryDelay,
allErrors,
});
if (result.type === "return") {
return result.value;
}
if (result.type === "break") {
break;
}
}
catch (error) {
if (await handleWhenThrow({
allErrors,
error,
errorPolicy,
onRetryDelay,
intervalAsTimeSpan,
attempt,
args,
context,
endDate,
})) {
break;
}
}
finally {
attempt++;
}
}
throwErrors({
allErrors,
throwLastError,
attempt,
timeAsTimeSpan,
intervalAsTimeSpan,
});
};
}
//# sourceMappingURL=retry-interval.js.map