VWED_server/services/execution/block_handlers.py

2562 lines
94 KiB
Python
Raw Normal View History

2025-04-30 16:57:46 +08:00
#!/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