llmforge
Version:
One API, every AI model, instant switching. Change from GPT-4 to Gemini to local models with a single config update. LLMForge is the lightweight, TypeScript-first solution for multi-provider AI applications with zero vendor lock-in.
84 lines • 3.15 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.RetryHandler = void 0;
const types_1 = require("../../types");
class RetryHandler {
constructor(config = {}) {
this.config = {
maxRetries: config.maxRetries || 3,
retryDelay: config.retryDelay || 1000,
exponentialBackoff: config.exponentialBackoff !== false,
retryableStatusCodes: config.retryableStatusCodes || [429, 500, 502, 503, 504],
};
}
async executeWithRetry(operation, context = 'operation') {
let lastError;
for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) {
try {
const result = await operation();
if (attempt > 0) {
console.log(`${context} succeeded on attempt ${attempt + 1}`);
}
return result;
}
catch (error) {
lastError = error;
if (attempt === this.config.maxRetries) {
console.error(`${context} failed after ${this.config.maxRetries + 1} attempts:`, lastError);
break;
}
if (!this.isRetryableError(error)) {
console.error(`${context} failed with non-retryable error:`, lastError);
throw error;
}
const delay = this.calculateDelay(attempt);
console.warn(`${context} failed on attempt ${attempt + 1}, retrying in ${delay}ms:`, lastError.message);
await this.sleep(delay);
}
}
throw lastError;
}
isRetryableError(error) {
// Check for specific error types
if (error instanceof types_1.NonRetryableError) {
return false;
}
if (error instanceof types_1.RetryableError) {
return true;
}
// Check for network errors
if (error.name === 'TypeError' && error.message.includes('fetch')) {
return true;
}
// Check for timeout errors
if (error.name === 'AbortError' || error.message.includes('timeout')) {
return true;
}
// Check for HTTP status codes
if (error.status || error.code) {
const statusCode = error.status || error.code;
return this.config.retryableStatusCodes.includes(statusCode);
}
// Default to non-retryable for unknown errors
return false;
}
calculateDelay(attempt) {
if (!this.config.exponentialBackoff) {
return this.config.retryDelay;
}
const baseDelay = this.config.retryDelay * Math.pow(2, attempt);
const jitter = Math.random() * 0.1 * baseDelay;
return Math.floor(baseDelay + jitter);
}
sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
updateConfig(newConfig) {
this.config = { ...this.config, ...newConfig };
}
getConfig() {
return { ...this.config };
}
}
exports.RetryHandler = RetryHandler;
//# sourceMappingURL=expo.js.map