Skip to content

Commit 0817d10

Browse files
authored
feat: Refactoring workflow executor (#6328)
1 parent f39ea5b commit 0817d10

4 files changed

Lines changed: 87 additions & 32 deletions

File tree

apps/application/workflow/i_node.py

Lines changed: 72 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from application.workflow.common import Node
1515
from application.workflow.message.struct.content import Content
1616
from application.workflow.status import Status
17+
from common.utils.logger import maxkb_logger
1718

1819

1920
class INode:
@@ -36,22 +37,37 @@ def __init__(self, node, workflow_manage, get_node_parameters: Callable[[Node],
3637
self.parameters = get_node_parameters(node)
3738
# 节点运行时产生的数据
3839
self.data = {}
40+
self._completed = False
41+
# ---- 锚点构造,全项目唯一的拼接点 ----
3942

40-
def next_success_nodes(self):
41-
edge_node_list = self.workflow_manage.workflow.get_next_edge_nodes(self.node.id)
42-
if edge_node_list is None:
43-
self.workflow_manage.next_nodes([])
44-
return
45-
self.workflow_manage.next_nodes(
46-
[en.node for en in edge_node_list if en.edge.sourceAnchorId == self.node.id + '_right'])
43+
def anchor(self, *parts):
44+
"""
45+
通用锚点: anchor('right') → '{id}_right',
46+
anchor(branch_id, 'right') → '{id}_{branch_id}_right'
47+
"""
48+
return '_'.join([self.node.id, *map(str, parts)])
4749

48-
def next_fail_nodes(self):
49-
edge_node_list = self.workflow_manage.workflow.get_next_edge_nodes(self.node.id)
50-
if edge_node_list is None:
51-
self.workflow_manage.next_nodes([])
52-
return
53-
self.workflow_manage.next_nodes(
54-
[en.node for en in edge_node_list if en.edge.sourceAnchorId == self.node.id + '_exception_right'])
50+
def success_anchor(self):
51+
"""
52+
成功锚点
53+
@return: 成功锚点
54+
"""
55+
return self.anchor('right')
56+
57+
def fail_anchor(self):
58+
"""
59+
失败锚点
60+
@return: 失败锚点
61+
"""
62+
return self.branch_anchor('exception')
63+
64+
def branch_anchor(self, branch_id):
65+
"""
66+
自定义锚点
67+
@param branch_id: 自定义分支id
68+
@return: 自定义锚点
69+
"""
70+
return self.anchor(branch_id, 'right')
5571

5672
def execute(self):
5773
pass
@@ -61,18 +77,55 @@ def run(self):
6177
运行节点
6278
@return: 不响应数据
6379
"""
64-
start_time = time.time()
80+
self.data['start_time'] = time.time()
6581
self.status = Status.RUNNING
66-
self.data['start_time'] = start_time
67-
self._run()
68-
self.data['run_time'] = time.time() - start_time
82+
try:
83+
self._run()
84+
except Exception as e:
85+
self.complete(Status.FAIL, error=e)
6986

7087
def _run(self):
7188
"""
7289
执行节点
7390
@return:
7491
"""
75-
return self.execute()
92+
self.execute()
93+
self.complete(Status.SUCCESS)
94+
95+
def complete(self, status, anchors=None, error=None):
96+
"""
97+
节点结束调用函数
98+
99+
@param status: 状态
100+
@param anchors 锚点信息
101+
@param error: 错误信息
102+
@return:
103+
"""
104+
if self._completed:
105+
return
106+
self._completed = True
107+
self.status = status
108+
if error:
109+
self.data['error'] = str(error)
110+
self.data['run_time'] = time.time() - self.data['start_time']
111+
if anchors is None:
112+
anchors = [self.success_anchor() if status == Status.SUCCESS else self.fail_anchor()]
113+
self._dispatch(anchors)
114+
self.workflow_manage.assertion_end()
115+
116+
def _dispatch(self, anchors):
117+
"""
118+
根据锚点执行下一个节点
119+
@param anchors: 锚点列表
120+
@return:不返回
121+
"""
122+
edge_node_list = self.workflow_manage.workflow.get_next_edge_nodes(self.node.id) or []
123+
known = {en.edge.sourceAnchorId for en in edge_node_list}
124+
unknown = set(anchors) - known
125+
if unknown and known:
126+
maxkb_logger.warning(f'node {self.node.id}: anchors {unknown} matched no edges, known={known}')
127+
self.workflow_manage.next_nodes(
128+
[en.node for en in edge_node_list if en.edge.sourceAnchorId in anchors])
76129

77130
def get_node_id(self):
78131
"""

apps/application/workflow/nodes/ai_chat_node/ai_chat_node.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -262,8 +262,6 @@ def execute(self):
262262
answer = self.get_context('answer')
263263
node_info = NodeInfo(self.get_node_id(), self.get_node_name(), Status.SUCCESS)
264264
self.write(TextContent(text_content_id, answer, Status.SUCCESS, node_info))
265-
self.status = Status.SUCCESS
266-
self.next_success_nodes()
267265

268266
def _generate_prompt_question(self, prompt, model, vision, image_list, video_list):
269267
images = []

apps/application/workflow/nodes/start_node/start_node.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,5 +107,3 @@ def execute(self):
107107
key = field.get('value')
108108
if key:
109109
self.workflow_manage.context[key] = workflow_variable.get(key, '')
110-
self.status = Status.SUCCESS
111-
self.next_success_nodes()

apps/application/workflow/workflow_manage.py

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ def __init__(self,
4747
@param workflow_type: 工作流类型
4848
@param parameters: 工作流使用到的其他数据
4949
"""
50+
self._lock = threading.Lock()
5051
self.done = False
5152
self.call_back = call_back
5253
self.workflow = workflow
@@ -65,10 +66,7 @@ def run(self):
6566

6667
def _run(self, node):
6768
self.nodes.append(node)
68-
try:
69-
node.run()
70-
except Exception as e:
71-
node.status = Status.FAIL
69+
node.run()
7270

7371
def next_nodes(self, nodes: Optional[List[Node]]):
7472
"""
@@ -77,18 +75,26 @@ def next_nodes(self, nodes: Optional[List[Node]]):
7775
@return:
7876
"""
7977
if nodes is None or len(nodes) == 0:
80-
self.assertion_end()
8178
return
82-
for node in nodes:
83-
self._run_async(get_node_class(node.type, self.workflow_type)(node, self, get_node_parameters))
79+
with self._lock:
80+
instances = [get_node_class(n.type, self.workflow_type)(n, self, get_node_parameters)
81+
for n in nodes]
82+
self.nodes.extend(instances)
83+
for inst in instances:
84+
self._run_async(inst)
8485

8586
def assertion_end(self):
8687
"""
8788
如果节点执行结束没有下一个节点 就结束工作流
8889
@return:
8990
"""
90-
if self.is_end():
91-
self.end()
91+
with self._lock:
92+
if self.done:
93+
return
94+
if not self.is_end():
95+
return
96+
self.done = True
97+
self.end()
9298

9399
def is_end(self):
94100
"""

0 commit comments

Comments
 (0)