From 3608d132c0fbdb193758ba9a9c0f1da725d2313a Mon Sep 17 00:00:00 2001 From: Mutasem Aldmour <4711238+mutdmour@users.noreply.github.com> Date: Fri, 12 Aug 2022 16:06:57 +0200 Subject: [PATCH] fix(editor): improve expression and parameters performance (#3874) * fix expr perf issue * refactor a bit --- .../editor-ui/src/components/CodeEdit.vue | 2 +- .../src/components/ExpressionInput.vue | 2 +- packages/editor-ui/src/components/Node.vue | 2 +- .../src/components/NodeDetailsView.vue | 4 +-- .../src/components/ParameterInput.vue | 2 +- .../src/components/VariableSelector.vue | 2 +- .../src/components/mixins/pushConnection.ts | 3 +- .../src/components/mixins/workflowHelpers.ts | 28 ++++++++++++++----- .../src/components/mixins/workflowRun.ts | 2 +- packages/editor-ui/src/views/NodeView.vue | 12 ++++---- 10 files changed, 36 insertions(+), 23 deletions(-) diff --git a/packages/editor-ui/src/components/CodeEdit.vue b/packages/editor-ui/src/components/CodeEdit.vue index 1b6ece36145e9..8330b3f86bb91 100644 --- a/packages/editor-ui/src/components/CodeEdit.vue +++ b/packages/editor-ui/src/components/CodeEdit.vue @@ -51,7 +51,7 @@ export default mixins( let runIndex = 0; const executedWorkflow: IExecutionResponse | null = this.$store.getters.getWorkflowExecution; - const workflow = this.getWorkflow(); + const workflow = this.getCurrentWorkflow(); const activeNode: INodeUi | null = this.$store.getters.activeNode; const parentNode = workflow.getParentNodes(activeNode!.name, inputName, 1); const nodeConnection = workflow.getNodeConnectionIndexes(activeNode!.name, parentNode[0]) || { diff --git a/packages/editor-ui/src/components/ExpressionInput.vue b/packages/editor-ui/src/components/ExpressionInput.vue index d68e45c7d84f6..a94da93cb30f9 100644 --- a/packages/editor-ui/src/components/ExpressionInput.vue +++ b/packages/editor-ui/src/components/ExpressionInput.vue @@ -56,7 +56,7 @@ export default mixins( }; }, workflow (): Workflow { - return this.getWorkflow(); + return this.getCurrentWorkflow(); }, }, watch: { diff --git a/packages/editor-ui/src/components/Node.vue b/packages/editor-ui/src/components/Node.vue index 2a336bb7d0ad0..ffceb54f90192 100644 --- a/packages/editor-ui/src/components/Node.vue +++ b/packages/editor-ui/src/components/Node.vue @@ -385,7 +385,7 @@ export default mixins( } }, setSubtitle() { - const nodeSubtitle = this.getNodeSubtitle(this.data, this.nodeType, this.getWorkflow()) || ''; + const nodeSubtitle = this.getNodeSubtitle(this.data, this.nodeType, this.getCurrentWorkflow()) || ''; this.nodeSubtitle = nodeSubtitle.includes(CUSTOM_API_CALL_KEY) ? '' diff --git a/packages/editor-ui/src/components/NodeDetailsView.vue b/packages/editor-ui/src/components/NodeDetailsView.vue index fb32a3c5d31d1..81668bd99796c 100644 --- a/packages/editor-ui/src/components/NodeDetailsView.vue +++ b/packages/editor-ui/src/components/NodeDetailsView.vue @@ -224,7 +224,7 @@ export default mixins( ); }, workflow(): Workflow { - return this.getWorkflow(); + return this.getCurrentWorkflow(); }, parentNodes(): string[] { if (this.activeNode) { @@ -344,7 +344,7 @@ export default mixins( this.$store.commit('ui/setNDVSessionId'); this.$externalHooks().run('dataDisplay.nodeTypeChanged', { - nodeSubtitle: this.getNodeSubtitle(node, this.activeNodeType, this.getWorkflow()), + nodeSubtitle: this.getNodeSubtitle(node, this.activeNodeType, this.getCurrentWorkflow()), }); setTimeout(() => { diff --git a/packages/editor-ui/src/components/ParameterInput.vue b/packages/editor-ui/src/components/ParameterInput.vue index 9bd3f598797b3..cc9c6d83f1b98 100644 --- a/packages/editor-ui/src/components/ParameterInput.vue +++ b/packages/editor-ui/src/components/ParameterInput.vue @@ -685,7 +685,7 @@ export default mixins( return shortPath.join('.'); }, workflow (): Workflow { - return this.getWorkflow(); + return this.getCurrentWorkflow(); }, }, methods: { diff --git a/packages/editor-ui/src/components/VariableSelector.vue b/packages/editor-ui/src/components/VariableSelector.vue index 2a16954dd9f38..331df87b49815 100644 --- a/packages/editor-ui/src/components/VariableSelector.vue +++ b/packages/editor-ui/src/components/VariableSelector.vue @@ -75,7 +75,7 @@ export default mixins( return this.getFilterResults(this.variableFilter.toLowerCase(), 0); }, workflow (): Workflow { - return this.getWorkflow(); + return this.getCurrentWorkflow(); }, }, methods: { diff --git a/packages/editor-ui/src/components/mixins/pushConnection.ts b/packages/editor-ui/src/components/mixins/pushConnection.ts index 3750e5ab4a5a0..46be03672c976 100644 --- a/packages/editor-ui/src/components/mixins/pushConnection.ts +++ b/packages/editor-ui/src/components/mixins/pushConnection.ts @@ -221,8 +221,7 @@ export const pushConnection = mixins( const runDataExecutedErrorMessage = this.$getExecutionError(runDataExecuted.data.resultData.error); - // @ts-ignore - const workflow = this.getWorkflow(); + const workflow = this.getCurrentWorkflow(); if (runDataExecuted.waitTill !== undefined) { const { activeExecutionId, diff --git a/packages/editor-ui/src/components/mixins/workflowHelpers.ts b/packages/editor-ui/src/components/mixins/workflowHelpers.ts index 183ac6024affa..9b9cddb655355 100644 --- a/packages/editor-ui/src/components/mixins/workflowHelpers.ts +++ b/packages/editor-ui/src/components/mixins/workflowHelpers.ts @@ -55,6 +55,9 @@ import { isEqual } from 'lodash'; import mixins from 'vue-typed-mixins'; import { v4 as uuid } from 'uuid'; +let cachedWorkflowKey: string | null = ''; +let cachedWorkflow: Workflow | null = null; + export const workflowHelpers = mixins( externalHooks, nodeHelpers, @@ -317,11 +320,20 @@ export const workflowHelpers = mixins( return nodeTypes; }, - // Returns a workflow instance. - getWorkflow (nodes?: INodeUi[], connections?: IConnections, copyData?: boolean): Workflow { - nodes = nodes || this.getNodes(); - connections = connections || (this.$store.getters.allConnections as IConnections); + getCurrentWorkflow(copyData?: boolean): Workflow { + const nodes = this.getNodes(); + const connections = (this.$store.getters.allConnections as IConnections); + const cacheKey = JSON.stringify({nodes, connections}); + if (cachedWorkflow && cacheKey === cachedWorkflowKey) { + return cachedWorkflow; + } + cachedWorkflowKey = cacheKey; + return this.getWorkflow(nodes, connections, copyData); + }, + + // Returns a workflow instance. + getWorkflow (nodes: INodeUi[], connections: IConnections, copyData?: boolean): Workflow { const nodeTypes = this.getNodeTypes(); let workflowId = this.$store.getters.workflowId; if (workflowId === PLACEHOLDER_EMPTY_WORKFLOW_ID) { @@ -330,7 +342,7 @@ export const workflowHelpers = mixins( const workflowName = this.$store.getters.workflowName; - return new Workflow({ + cachedWorkflow = new Workflow({ id: workflowId, name: workflowName, nodes: copyData ? JSON.parse(JSON.stringify(nodes)) : nodes, @@ -340,6 +352,8 @@ export const workflowHelpers = mixins( settings: this.$store.getters.workflowSettings, pinData: this.$store.getters.pinData, }); + + return cachedWorkflow; }, // Returns the currently loaded workflow as JSON. @@ -503,7 +517,7 @@ export const workflowHelpers = mixins( const itemIndex = 0; const inputName = 'main'; const activeNode = this.$store.getters.activeNode; - const workflow = this.getWorkflow(); + const workflow = this.getCurrentWorkflow(); const parentNode = workflow.getParentNodes(activeNode.name, inputName, 1); const executionData = this.$store.getters.getWorkflowExecution as IExecutionResponse | null; @@ -584,7 +598,7 @@ export const workflowHelpers = mixins( const returnData = this.resolveParameter(parameters) as IDataObject; if (typeof returnData['__xxxxxxx__'] === 'object') { - const workflow = this.getWorkflow(); + const workflow = this.getCurrentWorkflow(); return workflow.expression.convertObjectValueToString(returnData['__xxxxxxx__'] as object); } return returnData['__xxxxxxx__']; diff --git a/packages/editor-ui/src/components/mixins/workflowRun.ts b/packages/editor-ui/src/components/mixins/workflowRun.ts index 135823446d2be..a85a1c2fc7dec 100644 --- a/packages/editor-ui/src/components/mixins/workflowRun.ts +++ b/packages/editor-ui/src/components/mixins/workflowRun.ts @@ -60,7 +60,7 @@ export const workflowRun = mixins( return response; }, async runWorkflow (nodeName?: string, source?: string): Promise { - const workflow = this.getWorkflow(); + const workflow = this.getCurrentWorkflow(); if (this.$store.getters.isActionActive('workflowRunning') === true) { return; diff --git a/packages/editor-ui/src/views/NodeView.vue b/packages/editor-ui/src/views/NodeView.vue index c2af37c6478e8..d600db5b1a5ad 100644 --- a/packages/editor-ui/src/views/NodeView.vue +++ b/packages/editor-ui/src/views/NodeView.vue @@ -927,7 +927,7 @@ export default mixins( return; } - const workflow = this.getWorkflow(); + const workflow = this.getCurrentWorkflow(); if (!workflow.connectionsByDestinationNode.hasOwnProperty(lastSelectedNode.name)) { return; @@ -949,7 +949,7 @@ export default mixins( return; } - const workflow = this.getWorkflow(); + const workflow = this.getCurrentWorkflow(); if (!workflow.connectionsByDestinationNode.hasOwnProperty(lastSelectedNode.name)) { return; @@ -1036,7 +1036,7 @@ export default mixins( this.deselectAllNodes(); // Get all upstream nodes and select them - const workflow = this.getWorkflow(); + const workflow = this.getCurrentWorkflow(); for (const nodeName of workflow.getParentNodes(lastSelectedNode.name)) { this.nodeSelectedByName(nodeName); } @@ -1053,7 +1053,7 @@ export default mixins( this.deselectAllNodes(); // Get all downstream nodes and select them - const workflow = this.getWorkflow(); + const workflow = this.getCurrentWorkflow(); for (const nodeName of workflow.getChildNodes(lastSelectedNode.name)) { this.nodeSelectedByName(nodeName); } @@ -1064,7 +1064,7 @@ export default mixins( pushDownstreamNodes (sourceNodeName: string, margin: number) { const sourceNode = this.$store.getters.nodesByName[sourceNodeName]; - const workflow = this.getWorkflow(); + const workflow = this.getCurrentWorkflow(); const childNodes = workflow.getChildNodes(sourceNodeName); for (const nodeName of childNodes) { const node = this.$store.getters.nodesByName[nodeName] as INodeUi; @@ -2586,7 +2586,7 @@ export default mixins( }); // Rename the node and update the connections - const workflow = this.getWorkflow(undefined, undefined, true); + const workflow = this.getCurrentWorkflow(true); workflow.renameNode(currentName, newName); // Update also last selected node and exeuction data