VWED_server/services/execution/block_handlers.py
2025-04-30 16:57:46 +08:00

2562 lines
94 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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