2025-05-12 15:43:21 +08:00

1407 lines
60 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.

import logging
from typing import Dict, Any
from services.execution.task_context import TaskContext
from .base import BlockHandler, register_handler
from utils.logger import get_logger
from data.enum.task_block_record_enum import TaskBlockRecordStatus
from .model.block_name import ProgressBlockName
# 获取日志记录器
logger = get_logger("services.execution.handlers.progress")
# 条件判断块处理器
@register_handler(ProgressBlockName.IF)
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}")
if result:
# 条件为真为false分支创建未执行记录
if has_false_branch:
logger.info(f"条件为真为false分支创建未执行记录")
await self._create_not_executed_records(executor, block, "false", "条件为真不执行false分支")
# 条件为真优先执行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:
# 条件为假为true分支创建未执行记录
if has_true_branch:
logger.info(f"条件为假为true分支创建未执行记录")
await self._create_not_executed_records(executor, block, "true", "条件为假不执行true分支")
# 条件为假为default分支创建未执行记录如果true分支不存在但default存在
if not has_true_branch and has_default_branch:
logger.info(f"条件为假为default分支创建未执行记录")
await self._create_not_executed_records(executor, block, "default", "条件为假不执行default分支")
# 条件为假优先执行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
async def _create_not_executed_records(self, executor, block, branch_name, reason):
"""
为指定分支的所有子组件创建未执行状态的记录
Args:
executor: 块执行器
block: 父块定义
branch_name: 分支名称
reason: 未执行原因
"""
try:
# 获取分支下的所有子块
children = block.get("children", {}).get(branch_name, [])
if not children:
logger.info(f"分支 {branch_name} 下没有子块,无需创建未执行记录")
return
logger.info(f"为分支 {branch_name} 下的 {len(children)} 个子块创建未执行记录")
# 依次为每个子块创建记录
for i, child_block in enumerate(children):
child_id = child_block.get('id', 'unknown')
child_type = child_block.get('blockType', 'unknown')
child_name = child_block.get('name', f"block-{child_id}")
logger.info(f"为未执行的子块创建记录 [{i+1}/{len(children)}] - 名称: {child_name}, ID: {child_id}, 类型: {child_type}")
# 创建子块记录
block_record_id = await executor._create_block_record(child_block)
# 更新块记录状态为"未执行"
await executor._update_block_record(
block_record_id,
TaskBlockRecordStatus.NOT_EXECUTED, # 使用1002表示"未执行"状态
reason,
)
# 如果该子块还有子块,递归处理
if "children" in child_block and child_block.get("children"):
# 对每个可能的分支都创建未执行记录
for sub_branch_name, sub_children in child_block.get("children", {}).items():
if sub_children:
sub_reason = f"{reason},父块未执行"
await self._create_not_executed_records(executor, child_block, sub_branch_name, sub_reason)
except Exception as e:
logger.error(f"创建未执行记录失败: {str(e)}")
# 继续执行,不影响主流程
# 循环块处理器
@register_handler(ProgressBlockName.WHILE)
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")
run_once = False if run_once is None else run_once # 是否至少执行一次
retry_period = input_params.get("retryPeriod")
retry_period = 0 if retry_period is None else retry_period # 循环间隔(毫秒)
print_continuously = input_params.get("printContinuously")
print_continuously = False if print_continuously is None else print_continuously # 是否持续打印日志
print("loop_condition", loop_condition, "=============================================")
print("run_once", run_once, "=============================================")
print("retry_period", retry_period, "=============================================")
print("print_continuously", print_continuously, "=============================================")
# 迭代计数器
iterations = 0
# 创建块执行器
from services.execution.block_executor import BlockExecutor
executor = BlockExecutor(context)
# 获取当前循环块的ID和名称用于后续识别哪个break组件是作用于当前循环
current_loop_id = block.get("id")
current_loop_name = block.get("name")
logger.info(f"开始执行while循环块 - ID: {current_loop_id}, 名称: {current_loop_name}")
# 检查是否至少需要执行一次
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
# 检查第一次执行后是否有break信号
has_break = await self._check_for_break_signal(block, context)
if has_break:
logger.info(f"while循环(至少执行一次模式)检测到break信号提前结束循环")
break_result = {
"success": True,
"message": f"while循环第1次执行后检测到break信号提前结束循环",
"output": {
"iterations": iterations
}
}
# 记录执行结果
await self._record_task_log(block, break_result, context)
# 执行exit分支(如果有)
if "exit" in block.get("children", {}) and block["children"]["exit"]:
logger.info(f"循环被break中断执行exit分支")
await executor.execute_children(block, "exit")
return break_result
# 根据条件循环执行,不设最大迭代次数
while loop_condition:
# 检查是否取消
if context.is_task_canceled():
result = {
"success": False,
"message": "任务已被取消",
"is_canceled": True
}
# 记录执行结果
await self._record_task_log(block, result, context)
return result
# 检查是否有返回信号
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)
else:
# 即使没有重试间隔也强制每10次迭代释放一次事件循环
# 这确保了其他请求能够得到处理
if iterations % 10 == 0:
import asyncio
await asyncio.sleep(0.2) # 释放事件循环的最小时间
# 执行循环体
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
# 检查是否有break信号
has_break = await self._check_for_break_signal(block, context)
if has_break:
logger.info(f"while循环检测到break信号提前结束循环已完成 {iterations}")
break
# 重新获取循环条件
loop_condition = input_params.get("loopCondition", False)
# 循环结束后执行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
async def _check_for_break_signal(self, block: Dict[str, Any], context: TaskContext) -> bool:
"""
检查是否有break信号
Args:
block: 当前块定义
context: 任务上下文
Returns:
bool: 是否有break信号
"""
try:
# 遍历当前循环的子组件查找是否存在break组件及其执行情况
child_blocks = block.get("children", {}).get("default", [])
for child_block in child_blocks:
child_id = child_block.get("id")
child_name = child_block.get("name")
child_type = child_block.get("blockType")
# 直接子组件是break组件
if child_type == ProgressBlockName.BREAK:
# 检查该break组件是否执行过通过查询其输出
break_output = context.get_block_output(child_name)
if break_output and break_output.get("breakSignal"):
logger.info(f"检测到直接子组件break信号 - 组件名称: {child_name}, ID: {child_id}")
return True
# 子组件不是循环块因为嵌套循环内的break应作用于内层循环
elif child_type not in [ProgressBlockName.WHILE, ProgressBlockName.ITERATE_LIST, ProgressBlockName.REPEAT_NUM]:
# 递归检查子组件的子组件中是否有break
if "children" in child_block and child_block.get("children") and await self._check_nested_break(child_block, context):
logger.info(f"检测到嵌套break信号来自子组件 - 组件名称: {child_name}, ID: {child_id}")
return True
# 没有找到break信号
return False
except Exception as e:
logger.error(f"检查break信号失败: {str(e)}")
return False
async def _check_nested_break(self, block: Dict[str, Any], context: TaskContext) -> bool:
"""
递归检查嵌套组件中是否存在已执行的break组件
Args:
block: 要检查的块定义
context: 任务上下文
Returns:
bool: 是否存在已执行的break组件
"""
try:
# 获取所有可能的分支名称
branches = block.get("children", {}).keys()
# 遍历所有分支
for branch_name in branches:
branch_blocks = block.get("children", {}).get(branch_name, [])
# 遍历分支中的所有块
for child_block in branch_blocks:
child_id = child_block.get("id")
child_name = child_block.get("name")
child_type = child_block.get("blockType")
# 如果子块是循环块,则不继续向下递归检查
# 因为如果存在break应该作用于最近的循环块而不是外层循环
if child_type in [ProgressBlockName.WHILE, ProgressBlockName.ITERATE_LIST, ProgressBlockName.REPEAT_NUM]:
logger.info(f"检测到嵌套循环块,不向下递归 - 类型: {child_type}, 名称: {child_name}")
continue
# 子块是break块
elif child_type == ProgressBlockName.BREAK:
# 检查该break组件是否执行过通过查询其输出
break_output = context.get_block_output(child_name)
if break_output and break_output.get("breakSignal"):
logger.info(f"检测到嵌套break信号 - 组件名称: {child_name}, ID: {child_id}")
return True
# 子块是其他可能包含子组件的块(除了循环块)
elif "children" in child_block and child_block.get("children"):
# 递归检查子块中是否有break
if await self._check_nested_break(child_block, context):
return True
# 没有找到break信号
return False
except Exception as e:
logger.error(f"检查嵌套break组件失败: {str(e)}")
return False
# 等待块处理器
@register_handler(ProgressBlockName.WAIT)
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是数字
try:
# 转换为整数
if isinstance(timeout, str):
timeout = int(timeout)
# 转换为秒
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 ValueError:
# 参数转换失败
result = {
"success": False,
"message": f"等待执行失败: 无效的等待时间参数 '{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
@register_handler(ProgressBlockName.IF_ELSE)
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:
# 条件为真为else分支创建未执行记录
logger.info(f"条件为真为else分支创建未执行记录")
await self._create_not_executed_records(executor, block, "else", "条件为真不执行else分支")
# 执行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:
# 条件为假为if分支创建未执行记录
logger.info(f"条件为假为if分支创建未执行记录")
await self._create_not_executed_records(executor, block, "if", "条件为假不执行if分支")
# 执行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
async def _create_not_executed_records(self, executor, block, branch_name, reason):
"""
为指定分支的所有子组件创建未执行状态的记录
Args:
executor: 块执行器
block: 父块定义
branch_name: 分支名称
reason: 未执行原因
"""
try:
# 获取分支下的所有子块
children = block.get("children", {}).get(branch_name, [])
if not children:
logger.info(f"分支 {branch_name} 下没有子块,无需创建未执行记录")
return
logger.info(f"为分支 {branch_name} 下的 {len(children)} 个子块创建未执行记录")
# 依次为每个子块创建记录
for i, child_block in enumerate(children):
child_id = child_block.get('id', 'unknown')
child_type = child_block.get('blockType', 'unknown')
child_name = child_block.get('name', f"block-{child_id}")
logger.info(f"为未执行的子块创建记录 [{i+1}/{len(children)}] - 名称: {child_name}, ID: {child_id}, 类型: {child_type}")
# 创建子块记录
block_record_id = await executor._create_block_record(child_block)
# 更新块记录状态为"未执行"
await executor._update_block_record(
block_record_id,
TaskBlockRecordStatus.NOT_EXECUTED, # 使用1006表示"未执行"状态
reason,
)
# 如果该子块还有子块,递归处理
if "children" in child_block and child_block.get("children"):
# 对每个可能的分支都创建未执行记录
for sub_branch_name, sub_children in child_block.get("children", {}).items():
if sub_children:
sub_reason = f"{reason},父块未执行"
await self._create_not_executed_records(executor, child_block, sub_branch_name, sub_reason)
except Exception as e:
logger.error(f"创建未执行记录失败: {str(e)}")
# 继续执行,不影响主流程
# 遍历数组处理器
@register_handler(ProgressBlockName.ITERATE_LIST)
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 = []
# 获取当前循环块的ID和名称用于后续识别哪个break组件是作用于当前循环
current_loop_id = block.get("id")
current_loop_name = block.get("name")
logger.info(f"开始执行数组遍历块 - ID: {current_loop_id}, 名称: {current_loop_name}")
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
# 强制周期性释放事件循环,以便其他请求能够得到处理
if index % 10 == 0 and index > 0:
import asyncio
await asyncio.sleep(0.1) # 释放事件循环的最小时间
if context.get_variable("__RETURN__", False):
logger.info(f"检测到返回信号,提前结束重复执行")
break
# 设置循环变量,使子组件可以访问当前项和索引
context.set_variable("index", index)
context.set_variable("item", item)
context.set_block_output(block.get("name"), {"index": index, "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
# 分析是否有break信号
# 1. 先查找直接子组件是否有break组件
has_break = False
# 遍历当前循环的子组件查找是否存在break组件及其执行情况
child_blocks = block.get("children", {}).get("default", [])
for child_block in child_blocks:
child_id = child_block.get("id")
child_name = child_block.get("name")
child_type = child_block.get("blockType")
# 直接子组件是break组件
if child_type == ProgressBlockName.BREAK:
# 检查该break组件是否执行过通过查询其输出
break_output = context.get_block_output(child_name)
if break_output and break_output.get("breakSignal"):
logger.info(f"检测到直接子组件break信号 - 组件名称: {child_name}, ID: {child_id}")
has_break = True
break
# 子组件不是循环块因为嵌套循环内的break应作用于内层循环
elif child_type not in [ProgressBlockName.WHILE, ProgressBlockName.ITERATE_LIST, ProgressBlockName.REPEAT_NUM]:
# 递归检查子组件的子组件中是否有break
if "children" in child_block and child_block.get("children") and await self._check_nested_break(child_block, context):
logger.info(f"检测到嵌套break信号来自子组件 - 组件名称: {child_name}, ID: {child_id}")
has_break = True
break
# 2. 如果检测到break信号提前结束循环
if has_break:
logger.info(f"数组遍历检测到break信号提前结束循环已完成 {index+1}/{len(array_data)}")
await self._record_task_log(
block,
{"success": True, "message": f"{index+1}次循环, item={item}, 检测到break信号提前结束循环"},
context
)
break
# 3. 记录正常的循环执行
await self._record_task_log(
block,
{"success": True, "message": f"{index+1}次循环, item={item}"},
context
)
result = {
"success": True,
"message": f"数组遍历成功,共遍历了 {len(results)} 个元素",
"output": {
"iterationResults": results,
"count": len(results)
}
}
return result
except Exception as e:
result = {
"success": False,
"message": f"数组遍历执行失败: {str(e)}"
}
# 记录异常
await self._record_task_log(block, result, context)
return result
async def _check_nested_break(self, block: Dict[str, Any], context: TaskContext) -> bool:
"""
递归检查嵌套组件中是否存在已执行的break组件
Args:
block: 要检查的块定义
context: 任务上下文
Returns:
bool: 是否存在已执行的break组件
"""
try:
# 获取所有可能的分支名称
branches = block.get("children", {}).keys()
# 遍历所有分支
for branch_name in branches:
branch_blocks = block.get("children", {}).get(branch_name, [])
# 遍历分支中的所有块
for child_block in branch_blocks:
child_id = child_block.get("id")
child_name = child_block.get("name")
child_type = child_block.get("blockType")
# 如果子块是循环块,则不继续向下递归检查
# 因为如果存在break应该作用于最近的循环块而不是外层循环
if child_type in [ProgressBlockName.WHILE, ProgressBlockName.ITERATE_LIST, ProgressBlockName.REPEAT_NUM]:
logger.info(f"检测到嵌套循环块,不向下递归 - 类型: {child_type}, 名称: {child_name}")
continue
# 子块是break块
elif child_type == ProgressBlockName.BREAK:
# 检查该break组件是否执行过通过查询其输出
break_output = context.get_block_output(child_name)
if break_output and break_output.get("breakSignal"):
logger.info(f"检测到嵌套break信号 - 组件名称: {child_name}, ID: {child_id}")
return True
# 子块是其他可能包含子组件的块(除了循环块)
elif "children" in child_block and child_block.get("children"):
# 递归检查子块中是否有break
if await self._check_nested_break(child_block, context):
return True
# 没有找到break信号
return False
except Exception as e:
logger.error(f"检查嵌套break组件失败: {str(e)}")
return False
# 延迟处理器
@register_handler(ProgressBlockName.DELAY)
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_time是数字
try:
# 转换为整数
if isinstance(delay_time, str):
delay_time = int(delay_time)
# 转换为秒
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 ValueError:
# 参数转换失败
result = {
"success": False,
"message": f"延迟执行失败: 无效的延迟时间参数 '{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(ProgressBlockName.BREAK)
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)
context.set_block_output(block.get("name"), {"breakSignal": 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
# 返回块处理器
@register_handler(ProgressBlockName.RETURN)
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(ProgressBlockName.SERIAL_FLOW)
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(ProgressBlockName.PARALLEL_FLOW)
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": "没有子块需要执行",
}
# 记录执行结果
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(ProgressBlockName.REPEAT_NUM)
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 or num > 1000:
result = {
"success": False,
"message": "执行次数必须大于0且小于1000",
}
# 记录执行结果
await self._record_task_log(block, result, context)
return result
# 创建块执行器
from services.execution.block_executor import BlockExecutor
executor = BlockExecutor(context)
# 获取当前循环块的ID和名称用于后续识别哪个break组件是作用于当前循环
current_loop_id = block.get("id")
current_loop_name = block.get("name")
logger.info(f"开始执行重复执行N次块 - ID: {current_loop_id}, 名称: {current_loop_name}, 目标次数: {num}")
# 循环执行
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("__RETURN__", False):
logger.info(f"检测到返回信号,提前结束重复执行,已完成 {i}/{num}")
# 不需要重置返回信号,它需要向上传播
break
# 强制周期性释放事件循环,以便其他请求能够得到处理
if i % 10 == 0 and i > 0:
import asyncio
await asyncio.sleep(0.1) # 释放事件循环的最小时间
# 设置当前索引
# context.set_variable("index", i)
context.set_block_output(block.get("name"), {"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
# 检查是否有break信号
has_break = await self._check_for_break_signal(block, context)
if has_break:
logger.info(f"重复执行检测到break信号提前结束循环已完成 {i+1}/{num}")
break_result = {
"success": True,
"message": f"重复执行第{i+1}次检测到break信号提前结束执行",
"output": {
"iterations": i + 1,
"totalIterations": num,
"stoppedByBreak": True
}
}
# 记录执行结果
await self._record_task_log(block, break_result, context)
# 直接跳到完成分支处理
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": {
"iterations": len(results),
"totalIterations": num
}
}
await self._record_task_log(block, failed_complete, context)
return failed_complete
return break_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": {
"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": {
"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
async def _check_for_break_signal(self, block: Dict[str, Any], context: TaskContext) -> bool:
"""
检查是否有break信号
Args:
block: 当前块定义
context: 任务上下文
Returns:
bool: 是否有break信号
"""
try:
# 遍历当前循环的子组件查找是否存在break组件及其执行情况
child_blocks = block.get("children", {}).get("default", [])
for child_block in child_blocks:
child_id = child_block.get("id")
child_name = child_block.get("name")
child_type = child_block.get("blockType")
# 直接子组件是break组件
if child_type == ProgressBlockName.BREAK:
# 检查该break组件是否执行过通过查询其输出
break_output = context.get_block_output(child_name)
if break_output and break_output.get("breakSignal"):
logger.info(f"检测到直接子组件break信号 - 组件名称: {child_name}, ID: {child_id}")
return True
# 子组件不是循环块因为嵌套循环内的break应作用于内层循环
elif child_type not in [ProgressBlockName.WHILE, ProgressBlockName.ITERATE_LIST, ProgressBlockName.REPEAT_NUM]:
# 递归检查子组件的子组件中是否有break
if "children" in child_block and child_block.get("children") and await self._check_nested_break(child_block, context):
logger.info(f"检测到嵌套break信号来自子组件 - 组件名称: {child_name}, ID: {child_id}")
return True
# 没有找到break信号
return False
except Exception as e:
logger.error(f"检查break信号失败: {str(e)}")
return False
async def _check_nested_break(self, block: Dict[str, Any], context: TaskContext) -> bool:
"""
递归检查嵌套组件中是否存在已执行的break组件
Args:
block: 要检查的块定义
context: 任务上下文
Returns:
bool: 是否存在已执行的break组件
"""
try:
# 获取所有可能的分支名称
branches = block.get("children", {}).keys()
# 遍历所有分支
for branch_name in branches:
branch_blocks = block.get("children", {}).get(branch_name, [])
# 遍历分支中的所有块
for child_block in branch_blocks:
child_id = child_block.get("id")
child_name = child_block.get("name")
child_type = child_block.get("blockType")
# 如果子块是循环块,则不继续向下递归检查
# 因为如果存在break应该作用于最近的循环块而不是外层循环
if child_type in [ProgressBlockName.WHILE, ProgressBlockName.ITERATE_LIST, ProgressBlockName.REPEAT_NUM]:
logger.info(f"检测到嵌套循环块,不向下递归 - 类型: {child_type}, 名称: {child_name}")
continue
# 子块是break块
elif child_type == ProgressBlockName.BREAK:
# 检查该break组件是否执行过通过查询其输出
break_output = context.get_block_output(child_name)
if break_output and break_output.get("breakSignal"):
logger.info(f"检测到嵌套break信号 - 组件名称: {child_name}, ID: {child_id}")
return True
# 子块是其他可能包含子组件的块(除了循环块)
elif "children" in child_block and child_block.get("children"):
# 递归检查子块中是否有break
if await self._check_nested_break(child_block, context):
return True
# 没有找到break信号
return False
except Exception as e:
logger.error(f"检查嵌套break组件失败: {str(e)}")
return False
# 抛出异常处理器
@register_handler(ProgressBlockName.THROW_EXCEPTION)
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