ai-patterns
Version:
Production-ready TypeScript patterns to build solid and robust AI applications. Retry logic, circuit breakers, rate limiting, human-in-the-loop escalation, prompt versioning, response validation, context window management, and more—all with complete type
94 lines • 3.29 kB
JavaScript
;
/**
* Timeout Pattern - Limit execution time of operations
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.TimeoutDurations = void 0;
exports.timeout = timeout;
exports.createTimeoutSignal = createTimeoutSignal;
exports.combineSignals = combineSignals;
const common_1 = require("../types/common");
const errors_1 = require("../types/errors");
const timeout_1 = require("../types/timeout");
Object.defineProperty(exports, "TimeoutDurations", { enumerable: true, get: function () { return timeout_1.TimeoutDurations; } });
/**
* Timeout Pattern - Execute function with time limit
*/
async function timeout(options) {
const { execute: fn, timeoutMs, message = `Operation cancelled after ${timeoutMs}ms`, logger = common_1.defaultLogger, onTimeout, signal: externalSignal, } = options;
// Validation
if (timeoutMs <= 0) {
throw new errors_1.PatternError(`timeoutMs must be > 0, received: ${timeoutMs}`, errors_1.ErrorCode.INVALID_TIMEOUT);
}
const startTime = Date.now();
const controller = new AbortController();
const { signal: internalSignal } = controller;
// If external signal provided, combine with internal signal
if (externalSignal) {
if (externalSignal.aborted) {
throw new errors_1.PatternError("Operation cancelled before start", errors_1.ErrorCode.ABORTED);
}
externalSignal.addEventListener("abort", () => {
controller.abort();
});
}
// Create timeout timer
const timer = setTimeout(() => {
logger.warn(`Timeout after ${timeoutMs}ms`);
if (onTimeout) {
onTimeout();
}
controller.abort();
}, timeoutMs);
try {
// Execute function with signal
const value = await Promise.race([
fn(),
new Promise((_, reject) => {
internalSignal.addEventListener("abort", () => {
const duration = Date.now() - startTime;
const error = new errors_1.PatternError(message, errors_1.ErrorCode.TIMEOUT, undefined, { duration, timeoutMs });
error.duration = duration;
error.timedOut = true;
reject(error);
});
}),
]);
const duration = Date.now() - startTime;
logger.debug(`Operation completed in ${duration}ms`);
return {
value,
duration,
timedOut: false,
};
}
finally {
clearTimeout(timer);
}
}
/**
* Create an AbortSignal that aborts after a delay
*/
function createTimeoutSignal(timeoutMs) {
const controller = new AbortController();
setTimeout(() => controller.abort(), timeoutMs);
return controller.signal;
}
/**
* Combine multiple AbortSignals into one
* The combined signal aborts when any input signal aborts
*/
function combineSignals(...signals) {
const controller = new AbortController();
for (const signal of signals) {
if (signal.aborted) {
controller.abort();
break;
}
signal.addEventListener("abort", () => {
controller.abort();
});
}
return controller.signal;
}
//# sourceMappingURL=timeout.js.map