1406 lines
60 KiB
Python
Raw Normal View History

2025-04-30 16:57:46 +08:00
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", False) # 是否至少执行一次
retry_period = input_params.get("retryPeriod", 0) # 循环间隔(毫秒)
print_continuously = input_params.get("printContinuously", False) # 是否持续打印日志
# 迭代计数器
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.1) # 释放事件循环的最小时间
# 执行循环体
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) # 释放事件循环的最小时间
# 设置循环变量,使子组件可以访问当前项和索引
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)
}
}
# 记录执行结果
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_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": "没有子块需要执行",
"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(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:
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)
# 获取当前循环块的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("currentIndex", 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": {
"results": results,
"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": {
"results": results,
"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": {
"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
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