Skip to content

Commit 5deab75

Browse files
authored
fix(editor): Add visual-only waitingForNext execution state for slow networks (#16143)
1 parent 00083d5 commit 5deab75

File tree

9 files changed

+120
-8
lines changed

9 files changed

+120
-8
lines changed

packages/frontend/editor-ui/src/components/canvas/elements/nodes/render-types/CanvasNodeDefault.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ const {
3030
hasPinnedData,
3131
executionStatus,
3232
executionWaiting,
33+
executionWaitingForNext,
3334
executionRunning,
3435
hasRunData,
3536
hasIssues,
@@ -61,7 +62,7 @@ const classes = computed(() => {
6162
[$style.error]: hasIssues.value,
6263
[$style.pinned]: hasPinnedData.value,
6364
[$style.waiting]: executionWaiting.value ?? executionStatus.value === 'waiting',
64-
[$style.running]: executionRunning.value,
65+
[$style.running]: executionRunning.value || executionWaitingForNext.value,
6566
[$style.configurable]: renderOptions.value.configurable,
6667
[$style.configuration]: renderOptions.value.configuration,
6768
[$style.trigger]: renderOptions.value.trigger,

packages/frontend/editor-ui/src/components/canvas/elements/nodes/render-types/parts/CanvasNodeStatusIcons.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ const {
1616
hasIssues,
1717
executionStatus,
1818
executionWaiting,
19+
executionWaitingForNext,
1920
executionRunning,
2021
hasRunData,
2122
runDataIterations,
@@ -59,7 +60,7 @@ const dirtiness = computed(() =>
5960
<!-- Do nothing, unknown means the node never executed -->
6061
</div>
6162
<div
62-
v-else-if="executionRunning || executionStatus === 'running'"
63+
v-else-if="executionRunning || executionWaitingForNext || executionStatus === 'running'"
6364
data-test-id="canvas-node-status-running"
6465
:class="[$style.status, $style.running]"
6566
>

packages/frontend/editor-ui/src/composables/useCanvasMapping.test.ts

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ describe('useCanvasMapping', () => {
112112
status: 'new',
113113
running: false,
114114
waiting: undefined,
115+
waitingForNext: false,
115116
},
116117
issues: {
117118
items: [],
@@ -1202,6 +1203,98 @@ describe('useCanvasMapping', () => {
12021203
});
12031204
});
12041205

1206+
describe('nodeExecutionWaitingForNextById', () => {
1207+
it('should be true when already executed node is waiting for next', () => {
1208+
const workflowsStore = mockedStore(useWorkflowsStore);
1209+
const node1 = createTestNode({
1210+
name: 'Node 1',
1211+
});
1212+
const node2 = createTestNode({
1213+
name: 'Node 2',
1214+
});
1215+
const nodes = [node1, node2];
1216+
const connections = {};
1217+
1218+
const workflowObject = createTestWorkflowObject({
1219+
nodes,
1220+
connections,
1221+
});
1222+
1223+
workflowsStore.executingNode = [];
1224+
workflowsStore.lastAddedExecutingNode = node1.name;
1225+
workflowsStore.isWorkflowRunning = true;
1226+
1227+
const { nodeExecutionWaitingForNextById } = useCanvasMapping({
1228+
nodes: ref(nodes),
1229+
connections: ref(connections),
1230+
workflowObject: ref(workflowObject) as Ref<Workflow>,
1231+
});
1232+
1233+
expect(nodeExecutionWaitingForNextById.value[node1.id]).toBe(true);
1234+
expect(nodeExecutionWaitingForNextById.value[node2.id]).toBe(false);
1235+
});
1236+
1237+
it('should be false when workflow is not executing', () => {
1238+
const workflowsStore = mockedStore(useWorkflowsStore);
1239+
const node1 = createTestNode({
1240+
name: 'Node 1',
1241+
});
1242+
const node2 = createTestNode({
1243+
name: 'Node 2',
1244+
});
1245+
const nodes = [node1, node2];
1246+
const connections = {};
1247+
1248+
const workflowObject = createTestWorkflowObject({
1249+
nodes,
1250+
connections,
1251+
});
1252+
1253+
workflowsStore.executingNode = [];
1254+
workflowsStore.lastAddedExecutingNode = node1.name;
1255+
workflowsStore.isWorkflowRunning = false;
1256+
1257+
const { nodeExecutionWaitingForNextById } = useCanvasMapping({
1258+
nodes: ref(nodes),
1259+
connections: ref(connections),
1260+
workflowObject: ref(workflowObject) as Ref<Workflow>,
1261+
});
1262+
1263+
expect(nodeExecutionWaitingForNextById.value[node1.id]).toBe(false);
1264+
expect(nodeExecutionWaitingForNextById.value[node2.id]).toBe(false);
1265+
});
1266+
1267+
it('should be false when there are nodes that are executing', () => {
1268+
const workflowsStore = mockedStore(useWorkflowsStore);
1269+
const node1 = createTestNode({
1270+
name: 'Node 1',
1271+
});
1272+
const node2 = createTestNode({
1273+
name: 'Node 2',
1274+
});
1275+
const nodes = [node1, node2];
1276+
const connections = {};
1277+
1278+
const workflowObject = createTestWorkflowObject({
1279+
nodes,
1280+
connections,
1281+
});
1282+
1283+
workflowsStore.executingNode = [node2.name];
1284+
workflowsStore.lastAddedExecutingNode = node1.name;
1285+
workflowsStore.isWorkflowRunning = false;
1286+
1287+
const { nodeExecutionWaitingForNextById } = useCanvasMapping({
1288+
nodes: ref(nodes),
1289+
connections: ref(connections),
1290+
workflowObject: ref(workflowObject) as Ref<Workflow>,
1291+
});
1292+
1293+
expect(nodeExecutionWaitingForNextById.value[node1.id]).toBe(false);
1294+
expect(nodeExecutionWaitingForNextById.value[node2.id]).toBe(false);
1295+
});
1296+
});
1297+
12051298
describe('connections', () => {
12061299
it('should map connections to canvas connections', () => {
12071300
const [manualTriggerNode, setNode] = mockNodes.slice(0, 2);

packages/frontend/editor-ui/src/composables/useCanvasMapping.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,17 @@ export function useCanvasMapping({
327327
}, {}),
328328
);
329329

330+
const nodeExecutionWaitingForNextById = computed(() =>
331+
nodes.value.reduce<Record<string, boolean>>((acc, node) => {
332+
acc[node.id] =
333+
node.name === workflowsStore.lastAddedExecutingNode &&
334+
workflowsStore.executingNode.length === 0 &&
335+
workflowsStore.isWorkflowRunning;
336+
337+
return acc;
338+
}, {}),
339+
);
340+
330341
const nodeExecutionStatusById = computed(() =>
331342
nodes.value.reduce<Record<string, ExecutionStatus>>((acc, node) => {
332343
const tasks = workflowsStore.getWorkflowRunData?.[node.name] ?? [];
@@ -589,6 +600,7 @@ export function useCanvasMapping({
589600
execution: {
590601
status: nodeExecutionStatusById.value[node.id],
591602
waiting: nodeExecutionWaitingById.value[node.id],
603+
waitingForNext: nodeExecutionWaitingForNextById.value[node.id],
592604
running: nodeExecutionRunningById.value[node.id],
593605
},
594606
runData: {
@@ -704,6 +716,7 @@ export function useCanvasMapping({
704716
return {
705717
additionalNodePropertiesById,
706718
nodeExecutionRunDataOutputMapById,
719+
nodeExecutionWaitingForNextById,
707720
nodeIssuesById,
708721
nodeHasIssuesById,
709722
connections: mappedConnections,

packages/frontend/editor-ui/src/composables/useCanvasNode.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ export function useCanvasNode() {
5252

5353
const executionStatus = computed(() => data.value.execution.status);
5454
const executionWaiting = computed(() => data.value.execution.waiting);
55+
const executionWaitingForNext = computed(() => data.value.execution.waitingForNext);
5556
const executionRunning = computed(() => data.value.execution.running);
5657

5758
const runDataOutputMap = computed(() => data.value.runData.outputMap);
@@ -83,6 +84,7 @@ export function useCanvasNode() {
8384
hasIssues,
8485
executionStatus,
8586
executionWaiting,
87+
executionWaitingForNext,
8688
executionRunning,
8789
render,
8890
eventBus,

packages/frontend/editor-ui/src/composables/useExecutingNode.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@ import { ref } from 'vue';
1414
*/
1515
export function useExecutingNode() {
1616
const executingNode = ref<string[]>([]);
17+
const lastAddedExecutingNode = ref<string | null>(null);
1718

1819
function addExecutingNode(nodeName: string) {
1920
executingNode.value.push(nodeName);
21+
lastAddedExecutingNode.value = nodeName;
2022
}
2123

2224
function removeExecutingNode(nodeName: string) {
@@ -30,6 +32,7 @@ export function useExecutingNode() {
3032

3133
function clearNodeExecutionQueue() {
3234
executingNode.value = [];
35+
lastAddedExecutingNode.value = null;
3336
}
3437

3538
function isNodeExecuting(nodeName: string): boolean {
@@ -38,6 +41,7 @@ export function useExecutingNode() {
3841

3942
return {
4043
executingNode,
44+
lastAddedExecutingNode,
4145
addExecutingNode,
4246
removeExecutingNode,
4347
isNodeExecuting,

packages/frontend/editor-ui/src/composables/usePushConnection/handlers/nodeExecuteAfter.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,7 @@ export async function nodeExecuteAfter({ data: pushData }: NodeExecuteAfter) {
2727
}
2828

2929
workflowsStore.updateNodeExecutionData(pushData);
30-
31-
// Remove the node from the executing queue after a short delay
32-
// To allow the running spinner to show for at least 50ms
33-
setTimeout(() => {
34-
workflowsStore.removeExecutingNode(pushData.nodeName);
35-
}, 50);
30+
workflowsStore.removeExecutingNode(pushData.nodeName);
3631

3732
void assistantStore.onNodeExecution(pushData);
3833
void schemaPreviewStore.trackSchemaPreviewExecution(pushData);

packages/frontend/editor-ui/src/stores/workflows.store.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ export const useWorkflowsStore = defineStore(STORES.WORKFLOWS, () => {
163163

164164
const {
165165
executingNode,
166+
lastAddedExecutingNode,
166167
addExecutingNode,
167168
removeExecutingNode,
168169
isNodeExecuting,
@@ -1938,6 +1939,7 @@ export const useWorkflowsStore = defineStore(STORES.WORKFLOWS, () => {
19381939
subWorkflowExecutionError,
19391940
executionWaitingForWebhook,
19401941
executingNode,
1942+
lastAddedExecutingNode,
19411943
workflowsById,
19421944
nodeMetadata,
19431945
isInDebugMode,

packages/frontend/editor-ui/src/types/canvas.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ export interface CanvasNodeData {
123123
status?: ExecutionStatus;
124124
waiting?: string;
125125
running: boolean;
126+
waitingForNext?: boolean;
126127
};
127128
runData: {
128129
outputMap: ExecutionOutputMap;

0 commit comments

Comments
 (0)