@haandev/core
Version:
Core library for @haandev packages
89 lines (88 loc) • 2.09 kB
JavaScript
// src/enforcer/enforcer.ts
var sleep = (ms) => new Promise((res) => setTimeout(res, ms));
var enforcer = async (retrier, options) => {
const {
maxRetries = 3,
retryDelay = 1e3,
fix,
onFix,
onInvalid,
timeout = 1e4,
onStart,
isCancelled,
onCancelled,
onFixError,
abortSignal,
onTimeout
} = options;
let result;
let error;
let isAborted = false;
const abortHandler = async () => {
isAborted = true;
await onCancelled?.();
await finallyFn();
};
const finallyFn = async () => {
if (timeoutId) {
clearTimeout(timeoutId);
}
abortSignal?.removeEventListener("abort", abortHandler);
};
const success = () => Promise.resolve(result).finally(finallyFn);
const failure = () => Promise.reject(error).finally(finallyFn);
abortSignal?.addEventListener("abort", abortHandler);
await onStart?.();
if (isCancelled?.() || abortSignal?.aborted) {
error = new Error("Aborted");
await onCancelled?.();
return failure();
}
let timeoutId;
let isTimeouted = false;
if (timeout) {
timeoutId = setTimeout(() => {
isTimeouted = true;
}, timeout);
}
const check = async (attempt) => {
try {
result = await retrier(result, error, attempt);
return true;
} catch (err) {
error = err;
if (error?.message === "Aborted") isAborted = true;
return false;
}
};
if (await check(0)) return success();
onInvalid?.();
for (let attempt = 0; attempt < maxRetries; attempt++) {
if (isCancelled?.() || isAborted || abortSignal?.aborted) {
error = new Error("Aborted");
onCancelled?.();
return failure();
}
if (isTimeouted) {
onTimeout?.();
return failure();
}
let fixResult;
try {
fixResult = await fix?.(result);
} catch (err) {
onFixError?.(err);
}
if (await check(attempt + 1)) {
onFix?.(fixResult);
return success();
}
if (attempt < maxRetries - 1) {
await sleep(retryDelay);
}
}
return failure();
};
export {
enforcer
};