@memory-bank/mcp
Version:
Memory-enabled Co-Pilot (MCP) server for managing project documentation and context
82 lines • 3.22 kB
JavaScript
export const FILE_SYSTEM_BUSY = 'FILE_SYSTEM_BUSY';
export const TEMPORARY_ERROR = 'TEMPORARY_ERROR';
export const IO_ERROR = 'IO_ERROR';
/**
* Utility functions for retrying file system operations
*/
import { InfrastructureError, InfrastructureErrorCodes } from "../../../shared/errors/InfrastructureError.js";
import { logger } from "../../../shared/utils/logger.js";
/**
* Determines if an error is retryable
* @param error Error to check
* @returns True if the error is retryable, false otherwise
*/
export function isRetryableError(error) {
if (error instanceof Error) {
const errorCode = error.code;
if (typeof errorCode === 'string') {
const retryableCodes = ['EBUSY', 'ETIMEDOUT', 'ECONNRESET', 'EPIPE', 'EAGAIN', 'EACCES', 'EIO'];
return retryableCodes.includes(errorCode);
}
}
if (error instanceof InfrastructureError) {
return [
FILE_SYSTEM_BUSY,
TEMPORARY_ERROR,
IO_ERROR
].includes(error.code);
}
return false;
}
/**
* Retry a function with exponential backoff
* @param fn Function to retry
* @param options Retry options
* @returns Promise resolving to the result of the function
* @throws The last error if all retries fail
*/
export async function withRetry(fn, options = {}) {
const maxRetries = options.maxRetries ?? 3;
const baseDelay = options.baseDelay ?? 300;
const backoffFactor = options.backoffFactor ?? 2;
const maxDelay = options.maxDelay ?? 2000;
const retryableErrorFilter = options.retryableErrorFilter ?? isRetryableError;
let lastError;
let attempt = 0;
while (attempt <= maxRetries) {
try {
return await fn();
}
catch (error) {
lastError = error;
attempt++;
if (attempt > maxRetries || !retryableErrorFilter(error)) {
throw error;
}
const delay = Math.min(baseDelay * Math.pow(backoffFactor, attempt - 1), maxDelay);
logger.warn(`Operation failed (attempt ${attempt}/${maxRetries}), retrying in ${delay}ms: ${error instanceof Error ? error.message : 'Unknown error'}`);
await new Promise(resolve => setTimeout(resolve, delay));
}
}
throw lastError;
}
/**
* Wrapper for file system operations to automatically retry on retryable errors
* @param operation Operation name for logging
* @param fn Function to execute
* @param options Retry options
* @returns Promise resolving to the result of the function
*/
export async function withFileSystemRetry(operation, fn, options = {}) {
try {
return await withRetry(fn, options);
}
catch (error) {
logger.error(`File system operation '${operation}' failed after retries: ${error instanceof Error ? error.message : 'Unknown error'}`);
if (!(error instanceof InfrastructureError)) {
throw new InfrastructureError(InfrastructureErrorCodes.FILE_SYSTEM_ERROR, `File system operation '${operation}' failed: ${error instanceof Error ? error.message : 'Unknown error'}`, { originalError: error });
}
throw error;
}
}
//# sourceMappingURL=FileSystemRetryUtils.js.map