export interface ResourceConfig { /** 资源获取函数 */ resourceFn: (...args: T) => Promise; /** 失败后禁用时间(毫秒),默认 30 秒 */ disableTime?: number; /** 最大重试次数,默认 3 次 */ maxRetries?: number; /** 主动测试间隔(毫秒),默认 60 秒 */ healthCheckInterval?: number; /** 最大健康检查失败次数,超过后永久禁用,默认 5 次 */ maxHealthCheckFailures?: number; /** 健康检查函数,如果提供则优先使用此函数进行健康检查 */ healthCheckFn?: (...args: T) => Promise; /** 测试参数(用于健康检查) */ testArgs?: T; } interface ResourceTypeState { /** 资源配置 */ config: { resourceFn: (...args: any[]) => Promise; healthCheckFn?: (...args: any[]) => Promise; disableTime: number; maxRetries: number; healthCheckInterval: number; maxHealthCheckFailures: number; testArgs?: any[]; }; /** 是否启用 */ isEnabled: boolean; /** 禁用截止时间 */ disableUntil: number; /** 当前重试次数 */ currentRetries: number; /** 健康检查失败次数 */ healthCheckFailureCount: number; /** 是否永久禁用 */ isPermanentlyDisabled: boolean; /** 上次健康检查时间 */ lastHealthCheckTime: number; /** 成功次数统计 */ successCount: number; /** 失败次数统计 */ failureCount: number; } export class ResourceManager { private resourceTypes = new Map(); private destroyed = false; /** * 调用资源(自动注册或复用已有配置) */ async callResource( type: string, config: ResourceConfig, ...args: T ): Promise { if (this.destroyed) { throw new Error('ResourceManager has been destroyed'); } // 获取或创建资源类型状态 let state = this.resourceTypes.get(type); if (!state) { // 首次注册 state = { config: { resourceFn: config.resourceFn as (...args: any[]) => Promise, healthCheckFn: config.healthCheckFn as ((...args: any[]) => Promise) | undefined, disableTime: config.disableTime ?? 30000, maxRetries: config.maxRetries ?? 3, healthCheckInterval: config.healthCheckInterval ?? 60000, maxHealthCheckFailures: config.maxHealthCheckFailures ?? 20, testArgs: config.testArgs as any[] | undefined, }, isEnabled: true, disableUntil: 0, currentRetries: 0, healthCheckFailureCount: 0, isPermanentlyDisabled: false, lastHealthCheckTime: 0, successCount: 0, failureCount: 0, }; this.resourceTypes.set(type, state); } // 在调用前检查是否需要进行健康检查 await this.checkAndPerformHealthCheck(state); // 检查资源状态 if (state.isPermanentlyDisabled) { throw new Error(`Resource type '${type}' is permanently disabled (success: ${state.successCount}, failure: ${state.failureCount})`); } if (!this.isResourceAvailable(type)) { const disableUntilDate = new Date(state.disableUntil).toISOString(); throw new Error(`Resource type '${type}' is currently disabled until ${disableUntilDate} (success: ${state.successCount}, failure: ${state.failureCount})`); } // 调用资源 try { const result = await config.resourceFn(...args); this.onResourceSuccess(state); return result; } catch (error) { this.onResourceFailure(state); throw error; } } /** * 检查资源类型是否可用 */ isResourceAvailable (type: string): boolean { const state = this.resourceTypes.get(type); if (!state) { return true; // 未注册的资源类型视为可用 } if (state.isPermanentlyDisabled || !state.isEnabled) { return false; } return Date.now() >= state.disableUntil; } /** * 获取资源类型统计信息 */ getResourceStats (type: string): { successCount: number; failureCount: number; isEnabled: boolean; isPermanentlyDisabled: boolean } | null { const state = this.resourceTypes.get(type); if (!state) { return null; } return { successCount: state.successCount, failureCount: state.failureCount, isEnabled: state.isEnabled, isPermanentlyDisabled: state.isPermanentlyDisabled, }; } /** * 获取所有资源类型统计 */ getAllResourceStats (): Map { const stats = new Map(); for (const [type, state] of this.resourceTypes) { stats.set(type, { successCount: state.successCount, failureCount: state.failureCount, isEnabled: state.isEnabled, isPermanentlyDisabled: state.isPermanentlyDisabled, }); } return stats; } /** * 注销资源类型 */ unregister (type: string): boolean { return this.resourceTypes.delete(type); } /** * 销毁管理器 */ destroy (): void { if (this.destroyed) { return; } this.resourceTypes.clear(); this.destroyed = true; } /** * 检查并执行健康检查(如果需要) */ private async checkAndPerformHealthCheck (state: ResourceTypeState): Promise { // 如果资源可用或已永久禁用,无需健康检查 if (state.isEnabled && Date.now() >= state.disableUntil) { return; } if (state.isPermanentlyDisabled) { return; } const now = Date.now(); // 检查是否还在禁用期内 if (now < state.disableUntil) { return; } // 检查是否需要进行健康检查(根据间隔时间) if (now - state.lastHealthCheckTime < state.config.healthCheckInterval) { return; } // 执行健康检查 await this.performHealthCheck(state); } private async performHealthCheck (state: ResourceTypeState): Promise { state.lastHealthCheckTime = Date.now(); try { let healthCheckResult: boolean; if (state.config.healthCheckFn) { const testArgs = state.config.testArgs || []; healthCheckResult = await state.config.healthCheckFn(...testArgs); } else { const testArgs = state.config.testArgs || []; await state.config.resourceFn(...testArgs); healthCheckResult = true; } if (healthCheckResult) { // 健康检查成功,重新启用 state.isEnabled = true; state.disableUntil = 0; state.currentRetries = 0; state.healthCheckFailureCount = 0; } else { throw new Error('Health check function returned false'); } } catch { // 健康检查失败,增加失败计数 state.healthCheckFailureCount++; // 检查是否达到最大健康检查失败次数 if (state.healthCheckFailureCount >= state.config.maxHealthCheckFailures) { // 永久禁用资源 state.isPermanentlyDisabled = true; state.disableUntil = 0; } else { // 继续禁用一段时间 state.disableUntil = Date.now() + state.config.disableTime; } } } private onResourceSuccess (state: ResourceTypeState): void { state.currentRetries = 0; state.disableUntil = 0; state.healthCheckFailureCount = 0; state.successCount++; } private onResourceFailure (state: ResourceTypeState): void { state.currentRetries++; state.failureCount++; // 如果重试次数达到上限,禁用资源 if (state.currentRetries >= state.config.maxRetries) { state.disableUntil = Date.now() + state.config.disableTime; state.currentRetries = 0; } } } // 创建全局实例 export const resourceManager = new ResourceManager(); // 便捷函数 export async function registerResource ( type: string, config: ResourceConfig, ...args: T ): Promise { return resourceManager.callResource(type, config, ...args); }