/** * ExecutionStepManager - 可扩展的步骤执行框架 * * 提供步骤的动态添加、管理和执行,支持错误处理和状态回调 * * 主要功能: * - 步骤的动态添加和管理 * - 支持重试机制和错误处理 * - 提供执行状态回调 * - 支持并行和串行执行 * - 可扩展的步骤定义 * * @author Financial Analysis Platform Team * @version 1.0.0 */ // ============================================================================ // 类型定义 // ============================================================================ /** * 执行步骤接口 */ export interface ExecutionStep { /** 步骤唯一标识符 */ id: string; /** 步骤显示名称 */ name: string; /** 步骤详细描述 */ description: string; /** 执行函数(可选) */ execute?: () => Promise; } /** * 执行选项接口 */ export interface ExecutionOptions { /** 步骤开始回调 */ onStepStart?: (step: ExecutionStep, index: number, total: number) => void; /** 步骤完成回调 */ onStepComplete?: (step: ExecutionStep, index: number, total: number) => void; /** 步骤错误回调 */ onStepError?: (step: ExecutionStep, index: number, total: number, error: Error) => void; /** 全部完成回调 */ onComplete?: () => void; /** 执行错误回调 */ onError?: (error: Error) => void; /** 最大重试次数 */ maxRetries?: number; /** 重试延迟(毫秒) */ retryDelay?: number; /** 出错时是否继续执行 */ continueOnError?: boolean; } /** * 执行上下文接口 */ export interface ExecutionContext { /** 当前执行步骤 */ currentStep: ExecutionStep | null; /** 当前步骤索引 */ stepIndex: number; /** 总步骤数 */ totalSteps: number; /** 是否正在运行 */ isRunning: boolean; /** 是否有错误 */ hasError: boolean; /** 错误信息 */ errorMessage?: string; /** 重试次数 */ retryCount: number; /** 最大重试次数 */ maxRetries: number; /** 是否可重试 */ canRetry: boolean; } export class ExecutionStepManager { private steps: ExecutionStep[] = []; private context: ExecutionContext = { currentStep: null, stepIndex: 0, totalSteps: 0, isRunning: false, hasError: false, errorMessage: undefined, retryCount: 0, maxRetries: 0, canRetry: false }; private options: ExecutionOptions = {}; constructor(steps: ExecutionStep[] = [], options: ExecutionOptions = {}) { this.steps = [...steps]; this.options = { maxRetries: 2, retryDelay: 1000, continueOnError: false, ...options }; this.updateContext(); } /** * 添加执行步骤 */ addStep(step: ExecutionStep): void { this.steps.push(step); this.updateContext(); } /** * 批量添加执行步骤 */ addSteps(steps: ExecutionStep[]): void { this.steps.push(...steps); this.updateContext(); } /** * 插入步骤到指定位置 */ insertStep(index: number, step: ExecutionStep): void { this.steps.splice(index, 0, step); this.updateContext(); } /** * 移除步骤 */ removeStep(stepId: string): boolean { const index = this.steps.findIndex(step => step.id === stepId); if (index !== -1) { this.steps.splice(index, 1); this.updateContext(); return true; } return false; } /** * 清空所有步骤 */ clearSteps(): void { this.steps = []; this.updateContext(); } /** * 获取所有步骤 */ getSteps(): ExecutionStep[] { return [...this.steps]; } /** * 获取当前执行上下文 */ getContext(): ExecutionContext { return { ...this.context }; } /** * 更新执行选项 */ setOptions(options: ExecutionOptions): void { this.options = { ...this.options, ...options }; } /** * 执行所有步骤 */ async execute(): Promise { if (this.context.isRunning) { throw new Error('Execution is already in progress'); } if (this.steps.length === 0) { throw new Error('No steps to execute'); } this.context.isRunning = true; this.context.hasError = false; this.context.errorMessage = undefined; this.context.stepIndex = 0; this.context.retryCount = 0; this.context.maxRetries = this.options.maxRetries || 2; try { for (let i = 0; i < this.steps.length; i++) { const step = this.steps[i]; this.context.currentStep = step; this.context.stepIndex = i; // 通知步骤开始 this.options.onStepStart?.(step, i, this.steps.length); let stepSuccess = false; let lastError: Error | null = null; // 重试逻辑 for (let retryAttempt = 0; retryAttempt <= this.context.maxRetries; retryAttempt++) { try { this.context.retryCount = retryAttempt; // 如果是重试,等待一段时间 if (retryAttempt > 0 && this.options.retryDelay) { await new Promise(resolve => setTimeout(resolve, this.options.retryDelay)); } // 执行步骤(如果有执行函数) if (step.execute) { await step.execute(); } stepSuccess = true; break; // 成功执行,跳出重试循环 } catch (stepError) { lastError = stepError instanceof Error ? stepError : new Error(String(stepError)); // 如果还有重试机会,继续重试 if (retryAttempt < this.context.maxRetries) { console.warn(`Step "${step.name}" failed, retrying (${retryAttempt + 1}/${this.context.maxRetries + 1}):`, lastError.message); continue; } } } if (stepSuccess) { // 通知步骤完成 this.options.onStepComplete?.(step, i, this.steps.length); } else { // 所有重试都失败了 const error = lastError || new Error('Step execution failed'); // 更新错误状态 this.context.hasError = true; this.context.errorMessage = error.message; this.context.canRetry = true; // 通知步骤错误 this.options.onStepError?.(step, i, this.steps.length, error); // 如果不继续执行,抛出错误 if (!this.options.continueOnError) { throw error; } } } // 所有步骤执行完成 this.options.onComplete?.(); } catch (error) { const execError = error instanceof Error ? error : new Error(String(error)); // 通知执行错误 this.options.onError?.(execError); // 重新抛出错误 throw execError; } finally { this.context.isRunning = false; } } /** * 执行单个步骤 */ async executeStep(stepId: string): Promise { const stepIndex = this.steps.findIndex(step => step.id === stepId); if (stepIndex === -1) { throw new Error(`Step with id '${stepId}' not found`); } const step = this.steps[stepIndex]; this.context.currentStep = step; this.context.stepIndex = stepIndex; this.context.isRunning = true; this.context.hasError = false; this.context.errorMessage = undefined; try { // 通知步骤开始 this.options.onStepStart?.(step, stepIndex, this.steps.length); // 执行步骤 if (step.execute) { await step.execute(); } // 通知步骤完成 this.options.onStepComplete?.(step, stepIndex, this.steps.length); } catch (stepError) { const error = stepError instanceof Error ? stepError : new Error(String(stepError)); // 更新错误状态 this.context.hasError = true; this.context.errorMessage = error.message; // 通知步骤错误 this.options.onStepError?.(step, stepIndex, this.steps.length, error); throw error; } finally { this.context.isRunning = false; } } /** * 停止执行(如果正在运行) */ stop(): void { this.context.isRunning = false; } /** * 重试当前失败的步骤 */ async retry(): Promise { if (!this.context.hasError || !this.context.canRetry) { throw new Error('No failed step to retry'); } if (this.context.isRunning) { throw new Error('Execution is already in progress'); } // 重置错误状态 this.context.hasError = false; this.context.errorMessage = undefined; this.context.canRetry = false; // 重新执行从当前步骤开始 try { await this.execute(); } catch (error) { // 错误已经在execute方法中处理 throw error; } } /** * 重置执行状态 */ reset(): void { this.context = { currentStep: null, stepIndex: 0, totalSteps: this.steps.length, isRunning: false, hasError: false, errorMessage: undefined, retryCount: 0, maxRetries: this.options.maxRetries || 2, canRetry: false }; } /** * 检查是否正在执行 */ isRunning(): boolean { return this.context.isRunning; } /** * 检查是否有错误 */ hasError(): boolean { return this.context.hasError; } /** * 获取错误信息 */ getErrorMessage(): string | undefined { return this.context.errorMessage; } /** * 检查是否可以重试 */ canRetry(): boolean { return this.context.canRetry; } /** * 更新执行上下文 */ private updateContext(): void { this.context.totalSteps = this.steps.length; this.context.maxRetries = this.options.maxRetries || 2; if (!this.context.isRunning) { this.context.stepIndex = 0; this.context.currentStep = null; this.context.retryCount = 0; } } /** * 创建一个带有预定义步骤的管理器实例 */ static createWithSteps(steps: ExecutionStep[], options: ExecutionOptions = {}): ExecutionStepManager { return new ExecutionStepManager(steps, options); } /** * 创建一个空的管理器实例 */ static create(options: ExecutionOptions = {}): ExecutionStepManager { return new ExecutionStepManager([], options); } } /** * 预定义的执行步骤 */ export const DEFAULT_EXECUTION_STEPS: ExecutionStep[] = [ { id: 'fetch_financial_data', name: '正在读取财务数据', description: '从Tushare API获取公司财务指标数据' } ]; /** * 创建默认的执行步骤管理器 */ export function createDefaultStepManager(options: ExecutionOptions = {}): ExecutionStepManager { return ExecutionStepManager.createWithSteps(DEFAULT_EXECUTION_STEPS, options); }