mirror of
https://github.com/n8n-io/n8n.git
synced 2025-01-12 13:27:31 -08:00
perf(editor): Improve performance when opening large workflows with node issues (#7901)
This PR should improve performance when opening large workflows that contain node issues (Fixes ADO-1521) **Background** Main reason for this poor performance is that our `getCurrentWorkflow()` store getter is unnecessarily heavy but on top of that we are calling it more than we need. This addresses the second part of the issue by changing the following: - Pausing node issue processing while workflows are loading - Only getting current workflow once (instead for every node) when calling `refreshNodeIssues` **Benchmark** This was tested on a workflow attached to [this Linear ticket](https://linear.app/n8n/issue/ADO-1501/deliveryhero-enterprise-instance-very-slow-loading-workflows) and this fix brings down opening time from **~1m10s** to **~28s** on my laptop. **Tests** - [Latest e2e tests run](https://github.com/n8n-io/n8n/actions/runs/7060874994) https://community.n8n.io/t/ui-very-slow-with-more-than-100-nodes/8236/14
This commit is contained in:
parent
132d691cbf
commit
4bd7ae29f7
|
@ -126,6 +126,7 @@ describe('Debug', () => {
|
||||||
cy.url().should('not.include', '/debug');
|
cy.url().should('not.include', '/debug');
|
||||||
|
|
||||||
workflowPage.actions.executeWorkflow();
|
workflowPage.actions.executeWorkflow();
|
||||||
|
workflowPage.actions.zoomToFit();
|
||||||
workflowPage.actions.deleteNode(IF_NODE_NAME);
|
workflowPage.actions.deleteNode(IF_NODE_NAME);
|
||||||
|
|
||||||
executionsTab.actions.switchToExecutionsTab();
|
executionsTab.actions.switchToExecutionsTab();
|
||||||
|
|
|
@ -91,6 +91,7 @@ export const nodeHelpers = defineComponent({
|
||||||
// Updates all the issues on all the nodes
|
// Updates all the issues on all the nodes
|
||||||
refreshNodeIssues(): void {
|
refreshNodeIssues(): void {
|
||||||
const nodes = this.workflowsStore.allNodes;
|
const nodes = this.workflowsStore.allNodes;
|
||||||
|
const workflow = this.workflowsStore.getCurrentWorkflow();
|
||||||
let nodeType: INodeTypeDescription | null;
|
let nodeType: INodeTypeDescription | null;
|
||||||
let foundNodeIssues: INodeIssues | null;
|
let foundNodeIssues: INodeIssues | null;
|
||||||
|
|
||||||
|
@ -99,7 +100,7 @@ export const nodeHelpers = defineComponent({
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
nodeType = this.nodeTypesStore.getNodeType(node.type, node.typeVersion);
|
nodeType = this.nodeTypesStore.getNodeType(node.type, node.typeVersion);
|
||||||
foundNodeIssues = this.getNodeIssues(nodeType, node);
|
foundNodeIssues = this.getNodeIssues(nodeType, node, workflow);
|
||||||
if (foundNodeIssues !== null) {
|
if (foundNodeIssues !== null) {
|
||||||
node.issues = foundNodeIssues;
|
node.issues = foundNodeIssues;
|
||||||
}
|
}
|
||||||
|
@ -110,6 +111,7 @@ export const nodeHelpers = defineComponent({
|
||||||
getNodeIssues(
|
getNodeIssues(
|
||||||
nodeType: INodeTypeDescription | null,
|
nodeType: INodeTypeDescription | null,
|
||||||
node: INodeUi,
|
node: INodeUi,
|
||||||
|
workflow: Workflow,
|
||||||
ignoreIssues?: string[],
|
ignoreIssues?: string[],
|
||||||
): INodeIssues | null {
|
): INodeIssues | null {
|
||||||
const pinDataNodeNames = Object.keys(this.workflowsStore.getPinData || {});
|
const pinDataNodeNames = Object.keys(this.workflowsStore.getPinData || {});
|
||||||
|
@ -147,7 +149,6 @@ export const nodeHelpers = defineComponent({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const workflow = this.workflowsStore.getCurrentWorkflow();
|
|
||||||
const nodeInputIssues = this.getNodeInputIssues(workflow, node, nodeType);
|
const nodeInputIssues = this.getNodeInputIssues(workflow, node, nodeType);
|
||||||
if (nodeIssues === null) {
|
if (nodeIssues === null) {
|
||||||
nodeIssues = nodeInputIssues;
|
nodeIssues = nodeInputIssues;
|
||||||
|
|
|
@ -605,7 +605,7 @@ export const workflowHelpers = defineComponent({
|
||||||
typeUnknown: true,
|
typeUnknown: true,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
nodeIssues = this.getNodeIssues(nodeType.description, node, ['execution']);
|
nodeIssues = this.getNodeIssues(nodeType.description, node, workflow, ['execution']);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nodeIssues !== null) {
|
if (nodeIssues !== null) {
|
||||||
|
|
|
@ -692,6 +692,9 @@ export default defineComponent({
|
||||||
instance(): BrowserJsPlumbInstance {
|
instance(): BrowserJsPlumbInstance {
|
||||||
return this.canvasStore.jsPlumbInstance;
|
return this.canvasStore.jsPlumbInstance;
|
||||||
},
|
},
|
||||||
|
isLoading(): boolean {
|
||||||
|
return this.loadingService !== null;
|
||||||
|
},
|
||||||
currentWorkflowObject(): Workflow {
|
currentWorkflowObject(): Workflow {
|
||||||
return this.workflowsStore.getCurrentWorkflow();
|
return this.workflowsStore.getCurrentWorkflow();
|
||||||
},
|
},
|
||||||
|
@ -2697,10 +2700,6 @@ export default defineComponent({
|
||||||
|
|
||||||
this.dropPrevented = true;
|
this.dropPrevented = true;
|
||||||
this.workflowsStore.addConnection({ connection: connectionData });
|
this.workflowsStore.addConnection({ connection: connectionData });
|
||||||
this.uiStore.stateIsDirty = true;
|
|
||||||
if (!this.suspendRecordingDetachedConnections) {
|
|
||||||
this.historyStore.pushCommandToUndo(new AddConnectionCommand(connectionData));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.isReadOnlyRoute && !this.readOnlyEnv) {
|
if (!this.isReadOnlyRoute && !this.readOnlyEnv) {
|
||||||
NodeViewUtils.hideOutputNameLabel(info.sourceEndpoint);
|
NodeViewUtils.hideOutputNameLabel(info.sourceEndpoint);
|
||||||
|
@ -2742,8 +2741,14 @@ export default defineComponent({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.dropPrevented = false;
|
this.dropPrevented = false;
|
||||||
this.updateNodesInputIssues();
|
if (!this.isLoading) {
|
||||||
this.resetEndpointsErrors();
|
this.uiStore.stateIsDirty = true;
|
||||||
|
if (!this.suspendRecordingDetachedConnections) {
|
||||||
|
this.historyStore.pushCommandToUndo(new AddConnectionCommand(connectionData));
|
||||||
|
}
|
||||||
|
this.updateNodesInputIssues();
|
||||||
|
this.resetEndpointsErrors();
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue