#!/usr/bin/env python # -*- coding: utf-8 -*- """ 块处理器模块 提供对不同类型块的执行处理 """ import json import logging from abc import ABC, abstractmethod from typing import Dict, List, Any, Optional, Type, Callable from datetime import datetime from services.execution.task_context import TaskContext # 获取日志记录器 logger = logging.getLogger(__name__) # 块处理器注册表 _block_handlers = {} class BlockHandler(ABC): """ 块处理器抽象基类 所有具体的块处理器都应该继承这个类 """ @abstractmethod async def execute( self, block: Dict[str, Any], input_params: Dict[str, Any], context: TaskContext ) -> Dict[str, Any]: """ 执行块 Args: block: 块定义 input_params: 解析后的输入参数 context: 任务上下文 Returns: Dict[str, Any]: 执行结果,必须包含success字段 """ pass async def _record_task_log( self, block: Dict[str, Any], result: Dict[str, Any], context: TaskContext ) -> None: """ 记录任务日志 Args: block: 块定义 result: 执行结果 context: 任务上下文 """ from sqlalchemy import insert from data.models.tasklog import VWEDTaskLog from data.session import get_async_session import uuid from datetime import datetime try: # 创建任务日志记录 task_log_id = str(uuid.uuid4()) async with get_async_session() as session: stmt = insert(VWEDTaskLog).values( id=task_log_id, create_time=datetime.now(), level=1 if result.get("success", False) else 3, # 1: 信息, 3: 错误 message=json.dumps(result, ensure_ascii=False), task_block_id=block.get("id", "unknown"), task_id=context.task_def_id, task_record_id=context.task_record_id ) await session.execute(stmt) await session.commit() except Exception as e: logger.error(f"记录任务日志失败: {str(e)}") # 注册装饰器 def register_handler(block_type: str): """ 注册块处理器的装饰器 Args: block_type: 块类型 """ def decorator(cls): _block_handlers[block_type] = cls() return cls return decorator # 获取块处理器 def get_block_handler(block_type: str) -> Optional[BlockHandler]: """ 获取块处理器 Args: block_type: 块类型 Returns: Optional[BlockHandler]: 对应的块处理器,如果不存在则返回None """ return _block_handlers.get(block_type) # # =============================================子任务组件类======================================================== # # 子任务块处理器 # @register_handler("SubTaskBp") # class SubTaskBlockHandler(BlockHandler): # """子任务块处理器""" # # async def execute( # self, # block: Dict[str, Any], # input_params: Dict[str, Any], # context: TaskContext # ) -> Dict[str, Any]: # """执行子任务块""" # from sqlalchemy import select, insert # from data.models.taskdef import VWEDTaskDef # from data.models.taskrecord import VWEDTaskRecord # from data.session import get_async_session # from services.execution.task_executor import TaskExecutor # import uuid # import asyncio # # try: # # 获取子任务ID # subtask_id = block.get("refTaskDefId") # # if not subtask_id: # result = { # "success": False, # "message": "缺少子任务ID" # } # await self._record_task_log(block, result, context) # return result # # # 获取执行参数(确保默认值) # is_async = input_params.get("ifAsync", False) # 是否异步执行,默认False # specified_task_record_id = input_params.get("taskRecordId", None) # 指定的任务记录ID,默认None # # # 从input_params中提取出子任务需要的参数 # # 排除控制参数 # control_params = ["ifAsync", "taskRecordId"] # subtask_params = {} # for key, value in input_params.items(): # if key not in control_params: # subtask_params[key] = value # # logger.info(f"开始执行子任务: {subtask_id}, 异步执行: {is_async}, 指定ID: {specified_task_record_id}") # # # 确定任务记录ID # task_record_id = None # if specified_task_record_id: # # 检查指定的任务记录是否存在 # async with get_async_session() as session: # result = await session.execute( # select(VWEDTaskRecord).where(VWEDTaskRecord.id == specified_task_record_id) # ) # existing_record = result.scalars().first() # # if existing_record: # # 如果指定的任务记录ID已存在,则报错 # result = { # "success": False, # "message": f"指定的任务记录ID已存在: {specified_task_record_id}" # } # await self._record_task_log(block, result, context) # return result # else: # # 使用指定的ID创建新任务 # task_record_id = specified_task_record_id # logger.info(f"使用指定ID创建新任务记录: {task_record_id}") # # if not task_record_id: # # 如果未指定ID或指定的ID不存在,生成新ID # task_record_id = str(uuid.uuid4()) # logger.info(f"使用生成的任务记录ID: {task_record_id}") # # # 获取根任务记录ID - 如果当前任务有父任务,则根任务是父任务的根任务,否则是当前任务 # root_task_record_id = context.get_variable("rootTaskRecordId", context.task_record_id) # # # 查询任务定义 # async with get_async_session() as session: # result = await session.execute( # select(VWEDTaskDef).where(VWEDTaskDef.id == subtask_id) # ) # task_def = result.scalars().first() # # if not task_def: # result = { # "success": False, # "message": f"找不到子任务定义: {subtask_id}" # } # await self._record_task_log(block, result, context) # return result # # # 获取任务定义详情 # task_def_detail = task_def.detail # # # 创建任务记录 - 设置所有关键参数 # record_values = { # "id": task_record_id, # "def_id": subtask_id, # "def_label": task_def.label, # "def_version": task_def.version, # "created_on": datetime.now(), # "status": 0, # 初始状态 # "input_params": json.dumps(subtask_params, ensure_ascii=False), # "parent_task_record_id": context.task_record_id, # 设置父任务ID # "root_task_record_id": root_task_record_id, # 设置根任务ID # "periodic_task": task_def.periodic_task if hasattr(task_def, "periodic_task") else 0, # 继承周期任务属性 # "task_def_detail": task_def_detail # 设置任务定义详情 # } # # # 执行插入 # await session.execute( # insert(VWEDTaskRecord).values(record_values) # ) # await session.commit() # # # 创建任务执行器 # executor = TaskExecutor(task_record_id) # # # 根据是否异步执行采取不同的处理方式 # if is_async: # # 异步执行:启动任务但不等待结果 # # 初始化执行器 # init_success = await executor.initialize() # if not init_success: # result = { # "success": False, # "message": f"初始化子任务执行器失败: {executor.error_message}" # } # await self._record_task_log(block, result, context) # return result # # # 创建异步任务但不等待 # asyncio.create_task(executor.execute()) # # # 执行完成后记录日志 # result = { # "success": True, # "message": f"子任务已异步启动: {task_record_id}", # "output": { # "subtaskId": subtask_id, # "taskRecordId": task_record_id, # "async": True # } # } # await self._record_task_log(block, result, context) # return result # else: # # 同步执行:等待任务执行完成后返回结果 # # 初始化执行器 # init_success = await executor.initialize() # if not init_success: # result = { # "success": False, # "message": f"初始化子任务执行器失败: {executor.error_message}" # } # await self._record_task_log(block, result, context) # return result # # # 执行子任务并等待结果 # execute_result = await executor.execute() # # # 处理子任务执行结果 # success = execute_result.get("success", False) # message = execute_result.get("message", "子任务执行完成") # # # 记录子任务结果到上下文变量 # context.set_variable("subtaskResult", execute_result) # # # 获取子任务输出 # output = execute_result.get("result", {}) # # # 将子任务输出合并到当前上下文变量 # if isinstance(output, dict): # for key, value in output.items(): # variable_name = f"subtask_{key}" # context.set_variable(variable_name, value) # # # 执行完成后记录日志 # result = { # "success": success, # "message": message, # "output": { # "subtaskId": subtask_id, # "taskRecordId": task_record_id, # "async": False, # "output": output # } # } # await self._record_task_log(block, result, context) # return result # except Exception as e: # result = { # "success": False, # "message": f"子任务执行异常: {str(e)}" # } # await self._record_task_log(block, result, context) # return result # 根块处理器 @register_handler("RootBp") class RootBlockHandler(BlockHandler): """根块处理器""" async def execute( self, block: Dict[str, Any], input_params: Dict[str, Any], context: TaskContext ) -> Dict[str, Any]: """执行根块""" try: from services.execution.block_executor import BlockExecutor # 创建块执行器 executor = BlockExecutor(context) # 执行根块的子块 result = await executor.execute_children(block) # 记录执行结果 await self._record_task_log(block, result, context) return result except Exception as e: # 处理异常 result = { "success": False, "message": f"根块执行异常: {str(e)}" } # 记录异常 await self._record_task_log(block, result, context) return result # ========================================================脚本组件类================================================ # 设置任务变量块处理器 # @register_handler("SetTaskVariablesBp") # class SetTaskVariablesBlockHandler(BlockHandler): # """设置任务变量块处理器""" # # async def execute( # self, # block: Dict[str, Any], # input_params: Dict[str, Any], # context: TaskContext # ) -> Dict[str, Any]: # """执行设置任务变量块""" # try: # # 获取函数名和参数 # function_name = input_params.get("functionName") # function_args = input_params.get("functionArgs", {}) # # if not function_name: # result = { # "success": False, # "message": "缺少函数名" # } # # 记录执行结果 # await self._record_task_log(block, result, context) # return result # # # 调用脚本执行方法 # exec_result = await self._execute_script(function_name, function_args, context) # # # 如果执行成功,将变量保存到任务记录 # if exec_result.get("success", False): # await self._save_variables_to_database(context) # # # 记录执行结果 # await self._record_task_log(block, exec_result, context) # return exec_result # except Exception as e: # result = { # "success": False, # "message": f"设置任务变量失败: {str(e)}" # } # # 记录异常 # await self._record_task_log(block, result, context) # return result # # async def _execute_script( # self, # function_name: str, # function_args: Any, # context: TaskContext # ) -> Dict[str, Any]: # """ # 执行指定的脚本函数 # # Args: # function_name: 要执行的函数名 # function_args: 函数参数 # context: 任务上下文 # # Returns: # Dict[str, Any]: 执行结果 # """ # # 固定加载scripts/user_save/test1.py文件 # script_file = r"D:\jsw_code\project\VWED_task\scripts\user_save\test1.py" # logger.info(f"正在加载脚本文件: {script_file}") # # try: # # 动态加载脚本模块 # import importlib.util # import sys # import os # # # 检查文件是否存在 # if not os.path.exists(script_file): # return { # "success": False, # "message": f"脚本文件不存在: {script_file}" # } # # # 加载模块 # spec = importlib.util.spec_from_file_location("user_script", script_file) # if not spec: # return { # "success": False, # "message": f"无法加载脚本规范: {script_file}" # } # module = importlib.util.module_from_spec(spec) # sys.modules["user_script"] = module # spec.loader.exec_module(module) # # # 检查函数是否存在 # if not hasattr(module, function_name): # return { # "success": False, # "message": f"函数 {function_name} 在脚本 {script_file} 中不存在" # } # # 获取函数对象 # func = getattr(module, function_name) # # # 准备函数参数(处理不同类型的参数传递方式) # args = [] # kwargs = {} # # # 如果function_args是字典,将其作为关键字参数传递 # if isinstance(function_args, dict): # kwargs = function_args # # 如果function_args是列表,将其作为位置参数传递 # elif isinstance(function_args, list): # args = function_args # # 如果function_args是其他类型,将其作为单个位置参数传递 # elif function_args is not None: # args = [function_args] # # # 调用函数 # logger.info(f"调用函数 {function_name} 参数: args={args}, kwargs={kwargs}") # result_value = func(*args, **kwargs) # # # 检查是否是异步函数并等待结果 # import inspect # if inspect.iscoroutine(result_value): # import asyncio # result_value = await result_value # # logger.info(f"函数 {function_name} 执行结果: {result_value}") # # # 设置返回值到上下文 - 与ScriptBp不同,这里会更新所有变量 # if isinstance(result_value, dict): # # 如果返回值是字典,将字典中的每个键值对设置为任务变量 # for key, value in result_value.items(): # context.set_variable(key, value) # # result_message = f"脚本函数 {function_name} 执行成功,已更新 {len(result_value)} 个变量" # else: # # 如果返回值不是字典,将整个返回值设置为scriptResult变量 # context.set_variable("scriptResult", result_value) # result_message = f"脚本函数 {function_name} 执行成功,结果已保存为scriptResult变量" # # # 构建成功结果 # return { # "success": True, # "message": result_message, # "output": { # "result": result_value, # "functionName": function_name # } # } # # except Exception as e: # logger.error(f"执行脚本函数时发生异常: {str(e)}", exc_info=True) # return { # "success": False, # "message": f"执行脚本函数 {function_name} 失败: {str(e)}" # } # # async def _save_variables_to_database(self, context: TaskContext) -> None: # """ # 将任务变量保存到数据库的任务记录中 # # Args: # context: 任务上下文 # """ # try: # from sqlalchemy import update # from data.models.taskrecord import VWEDTaskRecord # from data.session import get_async_session # import json # # # 获取任务记录ID # task_record_id = context.task_record_id # # if not task_record_id: # logger.error("无法保存变量,任务记录ID为空") # return # # # 将任务变量转换为JSON字符串 # variables_json = json.dumps(context.variables, ensure_ascii=False) # # # 更新数据库记录 # async with get_async_session() as session: # stmt = update(VWEDTaskRecord).where(VWEDTaskRecord.id == task_record_id).values( # variables=variables_json # ) # await session.execute(stmt) # await session.commit() # # logger.info(f"已将任务变量保存到数据库记录 {task_record_id}") # # except Exception as e: # logger.error(f"保存任务变量到数据库失败: {str(e)}") # # # 脚本块处理器 # @register_handler("ScriptBp") # class ScriptBlockHandler(BlockHandler): # """脚本块处理器""" # # async def execute( # self, # block: Dict[str, Any], # input_params: Dict[str, Any], # context: TaskContext # ) -> Dict[str, Any]: # """执行脚本块""" # try: # # 获取函数名和参数 # function_name = input_params.get("functionName") # function_args = input_params.get("functionArgs", {}) # # if not function_name: # result = { # "success": False, # "message": "缺少函数名" # } # # 记录执行结果 # await self._record_task_log(block, result, context) # return result # # # 调用脚本执行方法 # exec_result = await self._execute_script(function_name, function_args, context) # # # 记录执行结果 # await self._record_task_log(block, exec_result, context) # return exec_result # except Exception as e: # result = { # "success": False, # "message": f"脚本执行失败: {str(e)}" # } # # 记录异常 # await self._record_task_log(block, result, context) # return result # # async def _execute_script( # self, # function_name: str, # function_args: Any, # context: TaskContext # ) -> Dict[str, Any]: # """ # 执行指定的脚本函数 # # Args: # function_name: 要执行的函数名 # function_args: 函数参数 # context: 任务上下文 # # Returns: # Dict[str, Any]: 执行结果 # """ # # 固定加载scripts/user_save/test1.py文件 # script_file = r"D:\jsw_code\project\VWED_task\scripts\user_save\test1.py" # logger.info(f"正在加载脚本文件: {script_file}") # # try: # # 动态加载脚本模块 # import importlib.util # import sys # import os # # # 检查文件是否存在 # if not os.path.exists(script_file): # return { # "success": False, # "message": f"脚本文件不存在: {script_file}" # } # # # 加载模块 # spec = importlib.util.spec_from_file_location("user_script", script_file) # if not spec: # return { # "success": False, # "message": f"无法加载脚本规范: {script_file}" # } # module = importlib.util.module_from_spec(spec) # sys.modules["user_script"] = module # spec.loader.exec_module(module) # # 检查函数是否存在 # if not hasattr(module, function_name): # return { # "success": False, # "message": f"函数 {function_name} 在脚本 {script_file} 中不存在" # } # # 获取函数对象 # func = getattr(module, function_name) # # # 准备函数参数(处理不同类型的参数传递方式) # args = [] # kwargs = {} # # # 如果function_args是字典,将其作为关键字参数传递 # if isinstance(function_args, dict): # kwargs = function_args # # 如果function_args是列表,将其作为位置参数传递 # elif isinstance(function_args, list): # args = function_args # # 如果function_args是其他类型,将其作为单个位置参数传递 # elif function_args is not None: # args = [function_args] # # # 调用函数 # logger.info(f"调用函数 {function_name} 参数: args={args}, kwargs={kwargs}") # result_value = func(*args, **kwargs) # # # 检查是否是异步函数并等待结果 # import inspect # if inspect.iscoroutine(result_value): # import asyncio # result_value = await result_value # # logger.info(f"函数 {function_name} 执行结果: {result_value}") # # # 设置返回值到上下文 # context.set_variable("scriptResult", result_value) # # # 构建成功结果 # return { # "success": True, # "message": f"脚本函数 {function_name} 执行成功", # "output": { # "result": result_value, # "functionName": function_name # } # } # # except Exception as e: # logger.error(f"执行脚本函数时发生异常: {str(e)}", exc_info=True) # return { # "success": False, # "message": f"执行脚本函数 {function_name} 失败: {str(e)}" # } # 打印块处理器 @register_handler("PrintBp") class PrintBlockHandler(BlockHandler): """打印块处理器""" async def execute( self, block: Dict[str, Any], input_params: Dict[str, Any], context: TaskContext ) -> Dict[str, Any]: """执行打印块""" try: # 获取消息参数 message = input_params.get("message", "") # 记录日志 logger.info(f"任务 {context.task_record_id} 打印: {message}") # 返回结果 result = { "success": True, "message": "打印成功", "output": { "message": message } } # 记录执行结果 await self._record_task_log(block, result, context) return result except Exception as e: result = { "success": False, "message": f"打印失败: {str(e)}" } # 记录异常 await self._record_task_log(block, result, context) return result # 条件判断块处理器 @register_handler("IfBp") class IfBlockHandler(BlockHandler): """条件判断块处理器""" async def execute( self, block: Dict[str, Any], input_params: Dict[str, Any], context: TaskContext ) -> Dict[str, Any]: """执行条件判断块""" try: # 获取条件参数 condition = input_params.get("condition") # 判断条件 result = bool(condition) # 创建块执行器 from services.execution.block_executor import BlockExecutor executor = BlockExecutor(context) # 检查块中所有可用的分支 children = block.get("children", {}) has_true_branch = "true" in children and children["true"] has_false_branch = "false" in children and children["false"] has_default_branch = "default" in children and children["default"] logger.info(f"条件判断块执行 - ID: {block.get('id')}, 条件结果: {result}") logger.info(f"可用分支情况 - true分支: {has_true_branch}, false分支: {has_false_branch}, default分支: {has_default_branch}") # 根据条件执行不同分支 if result: # 条件为真,优先执行true分支,如果没有则尝试执行default分支 if has_true_branch: logger.info(f"条件为真,执行true分支") branch_name = "true" elif has_default_branch: logger.info(f"条件为真但无true分支,执行default分支") branch_name = "default" else: logger.info(f"条件为真但无可执行分支") exec_result = { "success": True, "message": "条件为真,但没有找到true或default分支", "output": { "condition": result, "branch": "none", "executed": False } } # 记录执行结果 await self._record_task_log(block, exec_result, context) return exec_result else: # 条件为假,优先执行false分支 if has_false_branch: logger.info(f"条件为假,执行false分支") branch_name = "false" else: logger.info(f"条件为假且无false分支,不执行任何分支") exec_result = { "success": True, "message": "条件为假,没有找到false分支", "output": { "condition": result, "branch": "none", "executed": False } } # 记录执行结果 await self._record_task_log(block, exec_result, context) return exec_result # 执行选定的分支 if branch_name: branch_result = await executor.execute_children(block, branch_name) if not branch_result.get("success", False): logger.error(f"分支 {branch_name} 执行失败: {branch_result.get('message')}") # 记录执行结果 await self._record_task_log(block, branch_result, context) return branch_result logger.info(f"分支 {branch_name} 执行成功") exec_result = { "success": True, "message": f"条件判断成功,执行{branch_name}分支完成", "output": { "condition": result, "branch": branch_name, "executed": True } } # 记录执行结果 await self._record_task_log(block, exec_result, context) return exec_result # 正常情况不应该到达这里 exec_result = { "success": True, "message": "条件判断完成,未执行任何分支", "output": { "condition": result, "branch": "none", "executed": False } } # 记录执行结果 await self._record_task_log(block, exec_result, context) return exec_result except Exception as e: logger.error(f"条件判断执行异常: {str(e)}") exec_result = { "success": False, "message": f"条件判断失败: {str(e)}" } # 记录异常 await self._record_task_log(block, exec_result, context) return exec_result # 循环块处理器 @register_handler("WhileBp") class WhileBlockHandler(BlockHandler): """循环块处理器""" async def execute( self, block: Dict[str, Any], input_params: Dict[str, Any], context: TaskContext ) -> Dict[str, Any]: """执行循环块""" try: # 获取循环条件和相关配置 loop_condition = input_params.get("loopCondition", False) run_once = input_params.get("runOnce", False) # 是否至少执行一次 retry_period = input_params.get("retryPeriod", 0) # 循环间隔(毫秒) print_continuously = input_params.get("printContinuously", False) # 是否持续打印日志 # 设置最大迭代次数,防止无限循环 max_iterations = 1000 iterations = 0 # 创建块执行器 from services.execution.block_executor import BlockExecutor executor = BlockExecutor(context) # 检查是否至少需要执行一次 if run_once: # 执行一次循环体,无论条件是否满足 logger.info(f"执行while循环体(至少执行一次模式)") branch_result = await executor.execute_children(block, "default") if not branch_result.get("success", False): # 记录执行结果 await self._record_task_log(block, branch_result, context) return branch_result iterations += 1 # 根据条件循环执行 while loop_condition and iterations < max_iterations: # 检查是否取消 if context.is_task_canceled(): result = { "success": False, "message": "任务已被取消" } # 记录执行结果 await self._record_task_log(block, result, context) return result # 检查是否有中断或返回信号 if context.get_variable("__BREAK__", False): logger.info(f"检测到中断信号,提前结束循环,已完成 {iterations} 次") context.set_variable("__BREAK__", False) # 重置中断信号 break if context.get_variable("__RETURN__", False): logger.info(f"检测到返回信号,提前结束循环,已完成 {iterations} 次") # 不重置返回信号,它需要向上传播 break # 如果不是第一次执行且有重试间隔,则等待 if iterations > 0 and retry_period > 0: import asyncio await asyncio.sleep(retry_period / 1000) # 执行循环体 if print_continuously or iterations == 0: logger.info(f"执行while循环体,第 {iterations+1} 次迭代") branch_result = await executor.execute_children(block, "default") if not branch_result.get("success", False): # 记录执行结果 await self._record_task_log(block, branch_result, context) return branch_result iterations += 1 # 重新获取循环条件 loop_condition = input_params.get("loopCondition", False) # 检查是否达到最大迭代次数 if iterations >= max_iterations: logger.warning(f"循环达到最大迭代次数 {max_iterations},可能存在无限循环") result = { "success": False, "message": f"循环达到最大迭代次数 {max_iterations},可能存在无限循环" } # 记录执行结果 await self._record_task_log(block, result, context) return result # 循环结束后,执行exit分支 if "exit" in block.get("children", {}) and block["children"]["exit"]: logger.info(f"循环结束,执行exit分支") exit_result = await executor.execute_children(block, "exit") if not exit_result.get("success", False): # 记录执行结果 await self._record_task_log(block, exit_result, context) return exit_result result = { "success": True, "message": f"循环执行成功,共执行 {iterations} 次", "output": { "iterations": iterations } } # 记录执行结果 await self._record_task_log(block, result, context) return result except Exception as e: result = { "success": False, "message": f"循环执行失败: {str(e)}" } # 记录异常 await self._record_task_log(block, result, context) return result # 等待块处理器 @register_handler("WaitBp") class WaitBlockHandler(BlockHandler): """等待块处理器""" async def execute( self, block: Dict[str, Any], input_params: Dict[str, Any], context: TaskContext ) -> Dict[str, Any]: """执行等待块""" import asyncio try: # 获取等待时间参数(毫秒) timeout = input_params.get("timeout", 1000) # 转换为秒 timeout_sec = timeout / 1000 # 等待 await asyncio.sleep(timeout_sec) result = { "success": True, "message": f"等待 {timeout} 毫秒完成", "output": { "timeout": timeout } } # 记录执行结果 await self._record_task_log(block, result, context) return result except Exception as e: result = { "success": False, "message": f"等待执行失败: {str(e)}" } # 记录异常 await self._record_task_log(block, result, context) return result # 添加HTTP请求相关处理器 # HTTP GET请求处理器 # @register_handler("GetBp") # class HttpGetBlockHandler(BlockHandler): # """HTTP GET请求处理器""" # # async def execute( # self, # block: Dict[str, Any], # input_params: Dict[str, Any], # context: TaskContext # ) -> Dict[str, Any]: # """执行HTTP GET请求""" # import aiohttp # import asyncio # import json # # try: # # 获取请求参数 # url = input_params.get("url") # # # 处理headers参数 # headers = {} # header_param = input_params.get("header", {}) # # # 如果header是字符串,尝试解析JSON # if isinstance(header_param, str): # try: # header_data = json.loads(header_param) # # 检查解析后的数据是否为列表格式 [{"key0":"value0", "value0":"value"}, ...] # if isinstance(header_data, list): # for item in header_data: # # 寻找以key开头的键,如key0, key1等 # for key in [k for k in item if k.startswith('key')]: # if key in item and item[key]: # # 对应的value键应该是value0, value1等 # value_key = 'value' + key[3:] # if value_key in item and item[value_key]: # headers[item[key]] = item[value_key] # # 如果是字典格式,直接使用 # elif isinstance(header_data, dict): # headers = header_data # except json.JSONDecodeError: # logger.warning(f"无法解析headers JSON: {header_param}") # elif isinstance(header_param, dict): # headers = header_param # # retry = input_params.get("retry", False) # # # 确保retry_times为整数 # retry_times = input_params.get("retryTimes", 3) # if isinstance(retry_times, str): # try: # retry_times = int(retry_times) # except ValueError: # retry_times = 3 # # # 确保retry_interval为整数 # retry_interval = input_params.get("retryInterval", 1000) # if isinstance(retry_interval, str): # try: # retry_interval = int(retry_interval) # except ValueError: # retry_interval = 1000 # # if not url: # result = { # "success": False, # "message": "缺少请求URL" # } # # 记录执行结果 # await self._record_task_log(block, result, context) # return result # # # 执行HTTP请求 # attempt = 0 # max_attempts = 1 if not retry else retry_times + 1 # # while attempt < max_attempts: # try: # async with aiohttp.ClientSession() as session: # async with session.get(url, headers=headers) as response: # # 读取响应内容 # response_text = await response.text() # # # 尝试解析JSON # try: # response_json = await response.json() # context.set_variable("response", response_json) # except: # # 不是有效的JSON,保存为文本 # context.set_variable("response", response_text) # # result = { # "success": True, # "message": f"HTTP GET请求成功,状态码: {response.status}", # } # # 记录执行结果 # await self._record_task_log(block, result, context) # return result # except Exception as e: # attempt += 1 # if attempt >= max_attempts: # raise # # # 重试间隔 # await asyncio.sleep(retry_interval / 1000) # # except Exception as e: # result = { # "success": False, # "message": f"HTTP GET请求失败: {str(e)}" # } # # 记录异常 # await self._record_task_log(block, result, context) # return result # # # HTTP POST请求处理器 # @register_handler("PostBp") # class HttpPostBlockHandler(BlockHandler): # """HTTP POST请求处理器""" # # async def execute( # self, # block: Dict[str, Any], # input_params: Dict[str, Any], # context: TaskContext # ) -> Dict[str, Any]: # """执行HTTP POST请求""" # import aiohttp # import asyncio # import json # # try: # # 获取请求参数 # url = input_params.get("url") # params = input_params.get("param", "{}") # # # 处理headers参数 # headers = {} # header_param = input_params.get("header", {}) # # # 如果header是字符串,尝试解析JSON # if isinstance(header_param, str): # try: # header_data = json.loads(header_param) # # 检查解析后的数据是否为列表格式 [{"key0":"value0", "value0":"value"}, ...] # if isinstance(header_data, list): # for item in header_data: # # 寻找以key开头的键,如key0, key1等 # for key in [k for k in item if k.startswith('key')]: # if key in item and item[key]: # # 对应的value键应该是value0, value1等 # value_key = 'value' + key[3:] # if value_key in item and item[value_key]: # headers[item[key]] = item[value_key] # # 如果是字典格式,直接使用 # elif isinstance(header_data, dict): # headers = header_data # except json.JSONDecodeError: # logger.warning(f"无法解析headers JSON: {header_param}") # elif isinstance(header_param, dict): # headers = header_param # # media_type = input_params.get("mediaType", "JSON") # retry = input_params.get("retry", False) # # # 确保retry_times为整数 # retry_times = input_params.get("retryTimes", 3) # if isinstance(retry_times, str): # try: # retry_times = int(retry_times) # except ValueError: # retry_times = 3 # # # 确保retry_interval为整数 # retry_interval = input_params.get("retryInterval", 1000) # if isinstance(retry_interval, str): # try: # retry_interval = int(retry_interval) # except ValueError: # retry_interval = 1000 # # if not url: # result = { # "success": False, # "message": "缺少请求URL" # } # # 记录执行结果 # await self._record_task_log(block, result, context) # return result # # # 准备请求数据 # try: # if isinstance(params, str): # data = json.loads(params) # else: # data = params # except: # data = params # 如果无法解析为JSON,使用原始字符串 # # # 设置Content-Type # content_type = "application/json" # if media_type == "HTML": # content_type = "text/html" # elif media_type == "XML": # content_type = "application/xml" # elif media_type == "XWWWFORMURLENCODED": # content_type = "application/x-www-form-urlencoded" # elif media_type == "JAVASCRIPT": # content_type = "application/javascript" # # if "Content-Type" not in headers: # headers["Content-Type"] = content_type # # # 执行HTTP请求 # attempt = 0 # max_attempts = 1 if not retry else retry_times + 1 # while attempt < max_attempts: # try: # async with aiohttp.ClientSession() as session: # async with session.post(url, json=data, headers=headers) as response: # # 读取响应内容 # response_text = await response.text() # # # 尝试解析JSON # try: # response_json = await response.json() # context.set_variable("response", response_json) # except: # # 不是有效的JSON,保存为文本 # context.set_variable("response", response_text) # # result = { # "success": True, # "message": f"HTTP POST请求成功,状态码: {response.status}, 响应内容详情: {response_text}", # } # # 记录执行结果 # await self._record_task_log(block, result, context) # return result # except Exception as e: # attempt += 1 # if attempt >= max_attempts: # raise # # # 重试间隔 # await asyncio.sleep(retry_interval / 1000) # # except Exception as e: # result = { # "success": False, # "message": f"HTTP POST请求失败: {str(e)}" # } # # 记录异常 # await self._record_task_log(block, result, context) # return result # # 添加基础模块处理器 # 创建唯一ID处理器 @register_handler("CreateUuidBp") class CreateUuidBlockHandler(BlockHandler): """创建唯一ID处理器""" async def execute( self, block: Dict[str, Any], input_params: Dict[str, Any], context: TaskContext ) -> Dict[str, Any]: """创建唯一ID""" import uuid try: # 生成UUID generated_uuid = str(uuid.uuid4()) # 设置上下文变量 result = { "success": True, "message": "创建唯一ID成功", "output": { "uuid": generated_uuid, } } context.set_block_output(block.get("name"), {"uuid": generated_uuid}) # 记录执行结果 await self._record_task_log(block, result, context) return result except Exception as e: result = { "success": False, "message": f"创建唯一ID失败: {str(e)}" } # 记录异常 await self._record_task_log(block, result, context) return result # 当前时间戳处理器 @register_handler("CurrentTimeStampBp") class CurrentTimeStampBlockHandler(BlockHandler): """当前时间戳处理器""" async def execute( self, block: Dict[str, Any], input_params: Dict[str, Any], context: TaskContext ) -> Dict[str, Any]: """获取当前时间戳""" import time try: # 获取当前时间戳(毫秒) current_timestamp = int(time.time() * 1000) # 设置上下文变量 context.set_variable("currentTimeStamp", current_timestamp) result = { "success": True, "message": "获取当前时间戳成功", "output": { "timestamp": current_timestamp } } # 记录执行结果 await self._record_task_log(block, result, context) return result except Exception as e: result = { "success": False, "message": f"获取当前时间戳失败: {str(e)}" } # 记录异常 await self._record_task_log(block, result, context) return result # 当前时间处理器 @register_handler("TimestampBp") class TimestampBlockHandler(BlockHandler): """当前时间处理器""" async def execute( self, block: Dict[str, Any], input_params: Dict[str, Any], context: TaskContext ) -> Dict[str, Any]: """获取当前时间""" from datetime import datetime try: # 获取当前时间 current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") # 设置上下文变量 context.set_variable("timestamp", current_time) result = { "success": True, "message": "获取当前时间成功", "output": { "timestamp": current_time } } # 记录执行结果 await self._record_task_log(block, result, context) return result except Exception as e: result = { "success": False, "message": f"获取当前时间失败: {str(e)}" } # 记录异常 await self._record_task_log(block, result, context) return result # 字符串转JSON对象处理器 @register_handler("StringToJsonObjectBp") class StringToJsonObjectBlockHandler(BlockHandler): """字符串转JSON对象处理器""" async def execute( self, block: Dict[str, Any], input_params: Dict[str, Any], context: TaskContext ) -> Dict[str, Any]: """将字符串转换为JSON对象""" import json try: # 获取输入参数 convert_string = input_params.get("convertString", "") if not convert_string: result = { "success": False, "message": "转换字符串为空" } # 记录执行结果 await self._record_task_log(block, result, context) return result # 转换为JSON对象 json_object = json.loads(convert_string) # 设置输出参数 output = { "convertObject": json_object } result = { "success": True, "message": "字符串转换为JSON对象成功", "output": output } # 记录执行结果 await self._record_task_log(block, result, context) return result except json.JSONDecodeError as e: result = { "success": False, "message": f"字符串解析为JSON对象失败: {str(e)}" } # 记录异常 await self._record_task_log(block, result, context) return result except Exception as e: result = { "success": False, "message": f"字符串转换为JSON对象失败: {str(e)}" } # 记录异常 await self._record_task_log(block, result, context) return result # 字符串转JSON数组处理器 @register_handler("StringToJsonArrayBp") class StringToJsonArrayBlockHandler(BlockHandler): """字符串转JSON数组处理器""" async def execute( self, block: Dict[str, Any], input_params: Dict[str, Any], context: TaskContext ) -> Dict[str, Any]: """将字符串转换为JSON数组""" import json try: # 获取输入参数 convert_string = input_params.get("convertString", "") if not convert_string: result = { "success": False, "message": "转换字符串为空" } # 记录执行结果 await self._record_task_log(block, result, context) return result # 转换为JSON数组 json_array = json.loads(convert_string) # 验证是否为数组 if not isinstance(json_array, list): result = { "success": False, "message": "转换结果不是JSON数组" } # 记录执行结果 await self._record_task_log(block, result, context) return result # 设置输出参数 output = { "convertArray": json_array } result = { "success": True, "message": "字符串转换为JSON数组成功", "output": output } # 记录执行结果 await self._record_task_log(block, result, context) return result except json.JSONDecodeError as e: result = { "success": False, "message": f"字符串解析为JSON数组失败: {str(e)}" } # 记录异常 await self._record_task_log(block, result, context) return result except Exception as e: result = { "success": False, "message": f"字符串转换为JSON数组失败: {str(e)}" } # 记录异常 await self._record_task_log(block, result, context) return result # 添加流程控制模块处理器 # If-Else处理器 @register_handler("IfElseBp") class IfElseBlockHandler(BlockHandler): """If-Else处理器""" async def execute( self, block: Dict[str, Any], input_params: Dict[str, Any], context: TaskContext ) -> Dict[str, Any]: """执行If-Else条件判断块""" try: # 获取条件参数 condition = input_params.get("conditionIf") # 创建块执行器 from services.execution.block_executor import BlockExecutor executor = BlockExecutor(context) # 根据条件执行不同分支 if condition: # 执行if分支 branch_result = await executor.execute_children(block, "if") if not branch_result.get("success", False): # 记录执行结果 await self._record_task_log(block, branch_result, context) return branch_result result = { "success": True, "message": "条件为真,执行if分支成功", } # 记录执行结果 await self._record_task_log(block, result, context) return result else: # 执行else分支 branch_result = await executor.execute_children(block, "else") if not branch_result.get("success", False): # 记录执行结果 await self._record_task_log(block, branch_result, context) return branch_result result = { "success": True, "message": "条件为假,执行else分支成功", } # 记录执行结果 await self._record_task_log(block, result, context) return result except Exception as e: result = { "success": False, "message": f"If-Else条件判断执行失败: {str(e)}" } # 记录异常 await self._record_task_log(block, result, context) return result # If-Else-If处理器 @register_handler("IfElseIfBp") class IfElseIfBlockHandler(BlockHandler): """If-Else-If处理器""" async def execute( self, block: Dict[str, Any], input_params: Dict[str, Any], context: TaskContext ) -> Dict[str, Any]: """执行If-Else-If条件判断块""" try: # 获取条件参数 condition_if = input_params.get("conditionIf") condition_else_if = input_params.get("conditionElseIf") # 创建块执行器 from services.execution.block_executor import BlockExecutor executor = BlockExecutor(context) # 根据条件执行不同分支 if condition_if: # 执行if分支 branch_result = await executor.execute_children(block, "if") if not branch_result.get("success", False): # 记录执行结果 await self._record_task_log(block, branch_result, context) return branch_result result = { "success": True, "message": "条件if为真,执行if分支成功", "output": { "condition": "if", "branch": "if" } } # 记录执行结果 await self._record_task_log(block, result, context) return result elif condition_else_if: # 执行else_if分支 branch_result = await executor.execute_children(block, "else_if") if not branch_result.get("success", False): # 记录执行结果 await self._record_task_log(block, branch_result, context) return branch_result result = { "success": True, "message": "条件else-if为真,执行else-if分支成功", "output": { "condition": "else_if", "branch": "else_if" } } # 记录执行结果 await self._record_task_log(block, result, context) return result else: # 执行else分支 branch_result = await executor.execute_children(block, "else") if not branch_result.get("success", False): # 记录执行结果 await self._record_task_log(block, branch_result, context) return branch_result result = { "success": True, "message": "所有条件为假,执行else分支成功", "output": { "condition": "else", "branch": "else" } } # 记录执行结果 await self._record_task_log(block, result, context) return result except Exception as e: result = { "success": False, "message": f"If-Else-If条件判断执行失败: {str(e)}" } # 记录异常 await self._record_task_log(block, result, context) return result # 遍历数组处理器 @register_handler("IterateListBp") class IterateListBlockHandler(BlockHandler): """遍历数组处理器""" async def execute( self, block: Dict[str, Any], input_params: Dict[str, Any], context: TaskContext ) -> Dict[str, Any]: """执行数组遍历块""" try: # 获取数组参数 array_data = input_params.get("list", []) # 如果不是数组,尝试转换 if not isinstance(array_data, list): import json try: if isinstance(array_data, str): array_data = json.loads(array_data) else: result = { "success": False, "message": "提供的参数不是有效的数组" } # 记录执行结果 await self._record_task_log(block, result, context) return result except: result = { "success": False, "message": "提供的参数无法解析为数组" } # 记录执行结果 await self._record_task_log(block, result, context) return result # 创建块执行器 from services.execution.block_executor import BlockExecutor executor = BlockExecutor(context) # 遍历数组 results = [] for index, item in enumerate(array_data): # 检查是否取消 if context.is_task_canceled(): result = { "success": False, "message": "任务已被取消" } # 记录执行结果 await self._record_task_log(block, result, context) return result # 设置循环变量 context.set_variable("index", index) context.set_variable("item", item) # 执行循环体 loop_result = await executor.execute_children(block, "default") # 收集结果 results.append({ "index": index, "success": loop_result.get("success", False), "result": loop_result }) # 如果执行失败,提前退出 if not loop_result.get("success", False): result = { "success": False, "message": f"数组遍历在索引 {index} 处执行失败", "output": { "iterationResults": results, "failedAt": index } } # 记录执行结果 await self._record_task_log(block, result, context) return result result = { "success": True, "message": f"数组遍历成功,遍历了 {len(array_data)} 个元素", "output": { "iterationResults": results, "count": len(array_data) } } # 记录执行结果 await self._record_task_log(block, result, context) return result except Exception as e: result = { "success": False, "message": f"数组遍历执行失败: {str(e)}" } # 记录异常 await self._record_task_log(block, result, context) return result # 延迟处理器 @register_handler("DelayBp") class DelayBlockHandler(BlockHandler): """延迟处理器""" async def execute( self, block: Dict[str, Any], input_params: Dict[str, Any], context: TaskContext ) -> Dict[str, Any]: """执行延迟块""" import asyncio try: # 获取延迟时间参数(毫秒) delay_time = input_params.get("timeMillis", 1000) # 转换为秒 delay_sec = delay_time / 1000 # 等待 await asyncio.sleep(delay_sec) result = { "success": True, "message": f"延迟 {delay_time} 毫秒完成", "output": { "delayTime": delay_time } } # 记录执行结果 await self._record_task_log(block, result, context) return result except Exception as e: result = { "success": False, "message": f"延迟执行失败: {str(e)}" } # 记录异常 await self._record_task_log(block, result, context) return result # Break处理器 @register_handler("BreakBp") class BreakBlockHandler(BlockHandler): """Break处理器""" async def execute( self, block: Dict[str, Any], input_params: Dict[str, Any], context: TaskContext ) -> Dict[str, Any]: """执行break块,用于跳出循环""" try: # 设置上下文中的break标志 context.set_variable("__BREAK__", True) result = { "success": True, "message": "Break执行成功,将跳出当前循环", "output": { "breakSignal": True } } # 记录执行结果 await self._record_task_log(block, result, context) return result except Exception as e: result = { "success": False, "message": f"Break执行失败: {str(e)}" } # 记录异常 await self._record_task_log(block, result, context) return result # 添加数据库操作相关处理器 # 执行SQL处理器 @register_handler("JdbcExecuteBp") class JdbcExecuteBlockHandler(BlockHandler): """执行SQL处理器""" async def execute( self, block: Dict[str, Any], input_params: Dict[str, Any], context: TaskContext ) -> Dict[str, Any]: """执行SQL语句""" from sqlalchemy import text from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession from sqlalchemy.orm import sessionmaker import os try: # 获取SQL语句 sql = input_params.get("sql") if not sql: result = { "success": False, "message": "缺少SQL语句" } # 记录执行结果 await self._record_task_log(block, result, context) return result # 获取数据库连接信息 # 通常从配置中获取,这里简化使用环境变量或默认值 db_url = os.environ.get("DATABASE_URL", "sqlite+aiosqlite:///database.db") # 创建异步引擎和会话 engine = create_async_engine(db_url) async_session = sessionmaker( engine, expire_on_commit=False, class_=AsyncSession ) # 执行SQL async with async_session() as session: result = await session.execute(text(sql)) await session.commit() # 获取受影响的行数 row_count = result.rowcount if hasattr(result, 'rowcount') else 0 exec_result = { "success": True, "message": f"SQL执行成功,影响了 {row_count} 行", "output": { "rowCount": row_count } } # 记录执行结果 await self._record_task_log(block, exec_result, context) return exec_result except Exception as e: result = { "success": False, "message": f"SQL执行失败: {str(e)}" } # 记录异常 await self._record_task_log(block, result, context) return result # 查询SQL处理器 @register_handler("JdbcQueryBp") class JdbcQueryBlockHandler(BlockHandler): """查询SQL处理器""" async def execute( self, block: Dict[str, Any], input_params: Dict[str, Any], context: TaskContext ) -> Dict[str, Any]: """执行SQL查询""" from sqlalchemy import text from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession from sqlalchemy.orm import sessionmaker import os import json try: # 获取SQL语句 sql = input_params.get("sql") if not sql: return { "success": False, "message": "缺少SQL语句" } # 获取数据库连接信息 # 通常从配置中获取,这里简化使用环境变量或默认值 db_url = os.environ.get("DATABASE_URL", "sqlite+aiosqlite:///database.db") # 创建异步引擎和会话 engine = create_async_engine(db_url) async_session = sessionmaker( engine, expire_on_commit=False, class_=AsyncSession ) # 执行SQL查询 async with async_session() as session: result = await session.execute(text(sql)) # 处理结果 if result.returns_rows: # 获取列名 columns = result.keys() # 转换为字典列表 rows = [dict(zip(columns, row)) for row in result.fetchall()] # 转换为JSON字符串 result_json = json.dumps(rows) # 设置上下文变量 context.set_variable("resultSet", result_json) exec_result = { "success": True, "message": f"SQL查询成功,返回 {len(rows)} 条记录", "output": { "rowCount": len(rows), "resultSet": rows, "resultJson": result_json } } # 记录执行结果 await self._record_task_log(block, exec_result, context) return exec_result else: # 非查询语句,没有返回行 context.set_variable("resultSet", "[]") exec_result = { "success": True, "message": "SQL执行成功,没有返回数据", "output": { "rowCount": 0, "resultSet": [], "resultJson": "[]" } } # 记录执行结果 await self._record_task_log(block, exec_result, context) return exec_result except Exception as e: result = { "success": False, "message": f"SQL查询失败: {str(e)}" } # 记录异常 await self._record_task_log(block, result, context) return result # 检查任务实例ID是否存在处理器 @register_handler("CheckTaskRecordIdIsExistBp") class CheckTaskRecordIdIsExistBlockHandler(BlockHandler): """检查任务实例ID是否存在处理器""" async def execute( self, block: Dict[str, Any], input_params: Dict[str, Any], context: TaskContext ) -> Dict[str, Any]: """检查任务记录ID是否存在""" from sqlalchemy import text, select from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession from sqlalchemy.orm import sessionmaker from data.models import VWEDTaskRecord import os try: # 获取任务记录ID task_record_id = input_params.get("taskRecordId") if not task_record_id: result = { "success": False, "message": "缺少任务记录ID" } # 记录执行结果 await self._record_task_log(block, result, context) return result # 获取数据库连接信息 # 通常从配置中获取,这里简化使用环境变量或默认值 db_url = os.environ.get("DATABASE_URL", "sqlite+aiosqlite:///database.db") # 创建异步引擎和会话 engine = create_async_engine(db_url) async_session = sessionmaker( engine, expire_on_commit=False, class_=AsyncSession ) # 查询任务记录 async with async_session() as session: query = select(VWEDTaskRecord).where(VWEDTaskRecord.id == task_record_id) result = await session.execute(query) record = result.scalar_one_or_none() exists = record is not None # 设置上下文变量 context.set_variable("taskRecordIdIsExist", exists) exec_result = { "success": True, "message": f"任务记录ID {'存在' if exists else '不存在'}", "output": { "exists": exists, "taskRecordId": task_record_id } } # 记录执行结果 await self._record_task_log(block, exec_result, context) return exec_result except Exception as e: result = { "success": False, "message": f"检查任务记录ID是否存在失败: {str(e)}" } # 记录异常 await self._record_task_log(block, result, context) return result # 增强现有脚本处理器和添加脚本变量处理器 # 返回块处理器 @register_handler("ReturnBp") class ReturnBlockHandler(BlockHandler): """Return处理器,用于提前返回结果""" async def execute( self, block: Dict[str, Any], input_params: Dict[str, Any], context: TaskContext ) -> Dict[str, Any]: """执行return块,用于提前返回流程执行结果""" try: # 设置上下文中的return标志 context.set_variable("__RETURN__", True) # 获取可能的返回数据 return_data = input_params.get("data", {}) result = { "success": True, "message": "Return执行成功,将提前结束流程", "output": { "returnSignal": True, "returnData": return_data } } # 记录执行结果 await self._record_task_log(block, result, context) return result except Exception as e: result = { "success": False, "message": f"Return执行失败: {str(e)}" } # 记录异常 await self._record_task_log(block, result, context) return result # 串行执行块处理器 @register_handler("SerialFlowBp") class SerialFlowBlockHandler(BlockHandler): """串行执行块处理器""" async def execute( self, block: Dict[str, Any], input_params: Dict[str, Any], context: TaskContext ) -> Dict[str, Any]: """串行执行子块""" try: # 创建块执行器 from services.execution.block_executor import BlockExecutor executor = BlockExecutor(context) # 执行default分支下的所有子块 result = await executor.execute_children(block, "default") # 检查是否成功 if not result.get("success", False): # 记录执行结果 await self._record_task_log(block, result, context) return result final_result = { "success": True, "message": "串行执行完成", "output": result.get("output", {}) } # 记录执行结果 await self._record_task_log(block, final_result, context) return final_result except Exception as e: result = { "success": False, "message": f"串行执行失败: {str(e)}" } # 记录异常 await self._record_task_log(block, result, context) return result # 并行执行块处理器 @register_handler("ParallelFlowBp") class ParallelFlowBlockHandler(BlockHandler): """并行执行块处理器""" async def execute( self, block: Dict[str, Any], input_params: Dict[str, Any], context: TaskContext ) -> Dict[str, Any]: """并行执行子块""" import asyncio try: # 创建块执行器 from services.execution.block_executor import BlockExecutor # 获取子块 children = block.get("children", {}).get("default", []) if not children: result = { "success": True, "message": "没有子块需要执行", "output": {} } # 记录执行结果 await self._record_task_log(block, result, context) return result # 为每个子块创建一个执行任务 tasks = [] results = [] for child_block in children: # 为每个子块创建一个新的执行上下文(共享同一个任务上下文) executor = BlockExecutor(context) # 将子块包装为一个异步任务 task = asyncio.create_task(executor.execute_block(child_block)) tasks.append(task) # 等待所有任务完成 completed_tasks = await asyncio.gather(*tasks, return_exceptions=True) # 处理任务结果 all_success = True for i, result in enumerate(completed_tasks): if isinstance(result, Exception): results.append({ "success": False, "message": f"子块执行异常: {str(result)}", "index": i }) all_success = False else: results.append(result) if not result.get("success", False): all_success = False # 所有并行子块执行完成后,检查是否有后续处理 from services.execution.block_executor import BlockExecutor executor = BlockExecutor(context) # 根据执行结果处理后续分支 if all_success: # 执行成功分支 if "success" in block.get("children", {}) and block["children"]["success"]: logger.info(f"并行执行成功,执行success分支") success_result = await executor.execute_children(block, "success") if not success_result.get("success", False): # 记录执行结果 await self._record_task_log(block, success_result, context) return success_result else: # 执行失败分支 if "fail" in block.get("children", {}) and block["children"]["fail"]: logger.info(f"并行执行部分失败,执行fail分支") fail_result = await executor.execute_children(block, "fail") if not fail_result.get("success", False): # 记录执行结果 await self._record_task_log(block, fail_result, context) return fail_result # 执行完成分支(无论成功失败) if "complete" in block.get("children", {}) and block["children"]["complete"]: logger.info(f"并行执行完成,执行complete分支") complete_result = await executor.execute_children(block, "complete") if not complete_result.get("success", False): # 记录执行结果 await self._record_task_log(block, complete_result, context) return complete_result final_result = { "success": all_success, "message": "并行执行完成" if all_success else "并行执行部分失败", "output": { "results": results, "allSuccess": all_success } } # 记录执行结果 await self._record_task_log(block, final_result, context) return final_result except Exception as e: result = { "success": False, "message": f"并行执行失败: {str(e)}" } # 记录异常 await self._record_task_log(block, result, context) return result # 并发执行N次处理器 @register_handler("ParallelRepeatNBp") class ParallelRepeatNBlockHandler(BlockHandler): """并发执行N次处理器""" async def execute( self, block: Dict[str, Any], input_params: Dict[str, Any], context: TaskContext ) -> Dict[str, Any]: """并发执行子块N次""" import asyncio try: # 获取执行次数 num = int(input_params.get("num", 1)) # 限制最大执行次数 num = min(num, 100) if num <= 0: result = { "success": True, "message": "执行次数必须大于0", "output": {} } # 记录执行结果 await self._record_task_log(block, result, context) return result # 创建块执行器 from services.execution.block_executor import BlockExecutor # 为每次执行创建一个执行任务 tasks = [] results = [] for i in range(num): # 为每次执行创建一个新的执行上下文(共享同一个任务上下文) executor = BlockExecutor(context) context.set_variable("index", i) # 执行default分支下的子块 task = asyncio.create_task(executor.execute_children(block, "default")) tasks.append(task) # 等待所有任务完成 completed_tasks = await asyncio.gather(*tasks, return_exceptions=True) # 处理任务结果 all_success = True for i, result in enumerate(completed_tasks): if isinstance(result, Exception): results.append({ "success": False, "message": f"第{i+1}次执行异常: {str(result)}", "index": i }) all_success = False else: results.append(result) if not result.get("success", False): all_success = False final_result = { "success": all_success, "message": f"并发执行{num}次完成" if all_success else f"并发执行{num}次部分失败", "output": { "results": results, "iterations": num } } # 记录执行结果 await self._record_task_log(block, final_result, context) return final_result except Exception as e: result = { "success": False, "message": f"并发执行N次失败: {str(e)}" } # 记录异常 await self._record_task_log(block, result, context) return result # 重复执行N次处理器 @register_handler("RepeatNumBp") class RepeatNumBlockHandler(BlockHandler): """重复执行N次处理器""" async def execute( self, block: Dict[str, Any], input_params: Dict[str, Any], context: TaskContext ) -> Dict[str, Any]: """重复执行子块N次""" try: # 获取执行次数 num = int(input_params.get("num", 1)) # 限制最大执行次数 num = min(num, 1000) if num <= 0: result = { "success": True, "message": "执行次数必须大于0", "output": {} } # 记录执行结果 await self._record_task_log(block, result, context) return result # 创建块执行器 from services.execution.block_executor import BlockExecutor executor = BlockExecutor(context) # 循环执行 results = [] for i in range(num): # 检查是否取消 if context.is_task_canceled(): result = { "success": False, "message": "任务已被取消" } # 记录执行结果 await self._record_task_log(block, result, context) return result # 检查是否有中断或返回信号 if context.get_variable("__BREAK__", False): logger.info(f"检测到中断信号,提前结束重复执行,已完成 {i}/{num} 次") context.set_variable("__BREAK__", False) # 重置中断信号 break if context.get_variable("__RETURN__", False): logger.info(f"检测到返回信号,提前结束重复执行,已完成 {i}/{num} 次") # 不需要重置返回信号,它需要向上传播 break # 设置当前索引 context.set_variable("index", i) # 执行子块 result = await executor.execute_children(block, "default") results.append({ "index": i, "success": result.get("success", False), "result": result }) # 如果执行失败,提前退出 if not result.get("success", False): failed_result = { "success": False, "message": f"重复执行在第 {i+1} 次时失败", "output": { "results": results, "iterations": i + 1, "totalIterations": num, "failedAt": i } } # 记录执行结果 await self._record_task_log(block, failed_result, context) return failed_result # 执行完成分支 if "complete" in block.get("children", {}) and block["children"]["complete"] and results: # 设置迭代信息 context.set_variable("count", len(results)) context.set_variable("lastIndex", len(results) - 1) complete_result = await executor.execute_children(block, "complete") if not complete_result.get("success", False): failed_complete = { "success": False, "message": f"完成分支执行失败: {complete_result.get('message')}", "output": { "results": results, "iterations": len(results), "totalIterations": num } } # 记录执行结果 await self._record_task_log(block, failed_complete, context) return failed_complete final_result = { "success": True, "message": f"重复执行成功,共执行 {len(results)} 次", "output": { "results": results, "iterations": len(results), "totalIterations": num } } # 记录执行结果 await self._record_task_log(block, final_result, context) return final_result except Exception as e: result = { "success": False, "message": f"重复执行N次失败: {str(e)}" } # 记录异常 await self._record_task_log(block, result, context) return result # 抛出异常处理器 @register_handler("ThrowExceptionBp") class ThrowExceptionBlockHandler(BlockHandler): """抛出异常处理器""" async def execute( self, block: Dict[str, Any], input_params: Dict[str, Any], context: TaskContext ) -> Dict[str, Any]: """抛出异常""" try: # 获取异常提示文本 message = input_params.get("message", "未知异常") # 记录日志 logger.error(f"主动抛出异常: {message}") # 这里实际上是返回失败结果,而不是真正抛出异常 # 这样可以更好地控制任务流程 result = { "success": False, "message": f"主动抛出异常: {message}", "output": { "exceptionMessage": message } } # 记录执行结果 await self._record_task_log(block, result, context) return result except Exception as e: result = { "success": False, "message": f"抛出异常块执行失败: {str(e)}" } # 记录异常 await self._record_task_log(block, result, context) return result # 停止其他并行分支处理器 @register_handler("StopOtherBranch") class StopOtherBranchBlockHandler(BlockHandler): """停止其他并行分支处理器""" async def execute( self, block: Dict[str, Any], input_params: Dict[str, Any], context: TaskContext ) -> Dict[str, Any]: """停止其他并行分支""" try: # 设置停止信号 context.set_variable("__STOP_OTHER_BRANCHES__", True) result = { "success": True, "message": "停止其他并行分支信号已设置", "output": { "stopSignal": True } } # 记录执行结果 await self._record_task_log(block, result, context) return result except Exception as e: result = { "success": False, "message": f"停止其他并行分支操作失败: {str(e)}" } # 记录异常 await self._record_task_log(block, result, context) return result