-
Notifications
You must be signed in to change notification settings - Fork 7.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(editor): Use pinned data to resolve expressions in unexecuted nodes #9693
Conversation
* master: fix(editor): Add back credential type icon (no-changelog) (#9704) feat(editor): Add canvas edge toolbar hover show/hide support (no-changelog) (#9699) ci: Fix custom docker builds (no-changelog) (#9702) test: Fix e2e for projects missing instance owner (no-changelog) (#9703) ci: Refactor e2e tests to be less flaky (no-changelog) (#9695) feat(editor): Add move resources option to workflows and credentials on (#9654) fix: Introduce `HooksService` (#8962) fix(editor): Improve large data warning in input/output panel (#9671) ci(editor): Enforce type-safety in @n8n/chat builds as well (no-changelog) (#9685) fix(editor): Un-skip workflow save test (no-changelog) (#9698) refactor(core): Remove more dead code from event bus (no-changelog) (#9697) ci: Remove unused WaitTracker mocking (no-changelog) (#9694) feat: Update NPS Value Survey (#9638) refactor(core): Remove event bus channel (no-changelog) (#9663) refactor(core): Remove event bus helpers (no-changelog) (#9690)
const workflowsStore = useWorkflowsStore(); | ||
|
||
if (workflowsStore.shouldReplaceInputDataWithPinData) { | ||
const parentPinData = parentNode.reduce<INodeExecutionData[]>((acc, parentNodeName, index) => { | ||
const pinData = workflowsStore.pinDataByNodeName(parentNodeName); | ||
|
||
if (pinData) { | ||
acc.push({ | ||
json: pinData[0], | ||
pairedItem: { | ||
item: index, | ||
input: 1, | ||
}, | ||
}); | ||
} | ||
|
||
return acc; | ||
}, []); | ||
|
||
if (parentPinData.length > 0) { | ||
if (connectionInputData && connectionInputData.length > 0) { | ||
parentPinData.forEach((parentPinDataEntry) => { | ||
connectionInputData![0].json = { | ||
...connectionInputData![0].json, | ||
...parentPinDataEntry.json, | ||
}; | ||
}); | ||
} else { | ||
connectionInputData = parentPinData; | ||
} | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cleaning this up, not necessary since WorkflowProxy now supports pinned data directly
@@ -0,0 +1,106 @@ | |||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
example workflow to test this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for tackling this! A bit spent today, will continue with fresh eyes tomorrow.
}: { nodeName?: string; branchIndex?: number; runIndex?: number; shortSyntax?: boolean } = {}) { | ||
if (nodeName === undefined) { | ||
return this.connectionInputData; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- When is
nodeName
not defined? I'm looking at all four callsites forgetNodeExecutionOrPinnedData
and all of them havenodeName
asstring
. Is this first check needed? - The original is setting defaults for some of the args - should we do that as well here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- removed
- getNodeExecutionData does the same. So I have left it for that.
export function getPinDataIfManualExecution( | ||
workflow: Workflow, | ||
nodeName: string, | ||
mode: WorkflowExecuteMode, | ||
): INodeExecutionData[] | undefined { | ||
const pinData = workflow.getPinDataOfNode(nodeName); | ||
if (pinData && mode === 'manual') { | ||
return pinData; | ||
} | ||
|
||
return undefined; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Can we do less work by checking for
mode
before getting pin data? - Any reason not to make this a method of
Workflow
? We're trying to move away from*Helpers
everywhere. - Would it make sense to make the
mode
check part of the existinggetPinDataOfNode
? Pin data should only be relevant for manual executions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- done
- I am not a fan of having to use
that
andthis
everywhere. Makes it harder to test and refactor. As well as understand what and when a value is set. That's why I prefer pure functions here. - I could see this being used without a manual execution, for example to validate or render data. Though it's not used currently as so. I would keep as is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- The point about
that
is valid, but I don't see how moving this method out ofWorkflow
helps there. Can we please move this method intoWorkflow
? 🙏🏽
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- We have to start somewhere breaking this apart. I don't want to balloon this PR with refactoring at the same time. I would opt to keep it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm torn - Workflow
is very much convoluted, but I think having more -Helper
files is not the way. In the end, this is not worth blocking over and we can revisit when we make an effort to simplify this class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's deal with this another time.
We've started writing tests and refactoring Workflow
, and it's possible that a lot of the code in here could be moved into the frontend, and we can then simplify this class.
@@ -349,39 +348,6 @@ function connectionInputData( | |||
} | |||
} | |||
|
|||
const workflowsStore = useWorkflowsStore(); | |||
|
|||
if (workflowsStore.shouldReplaceInputDataWithPinData) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see another use of shouldReplaceInputDataWithPinData
in useWorkflowHelpers
- that we cannot simplify also?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I checked that. That was actually necessary to set the input data for $input
and $json
to resolve for example.
@@ -360,7 +360,7 @@ export const useWorkflowsStore = defineStore(STORES.WORKFLOWS, () => { | |||
function getCurrentWorkflow(copyData?: boolean): Workflow { | |||
const nodes = getNodes(); | |||
const connections = allConnections.value; | |||
const cacheKey = JSON.stringify({ nodes, connections }); | |||
const cacheKey = JSON.stringify({ nodes, connections, pinData: pinnedWorkflowData.value }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Max pin data size I think defaults to 12 MB and can be customized to be even higher. getCurrentWorkflow
seems to be called from multiple spots.
Wondering - Could we have performance issues from frequently stringifying a very large JS object? Is there a limit to how long a key can be?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's no limit. I don't have a quick solution here. But removing this caching is much worse for performance.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This whole method is performance nightmare, and one of the leading culprits behind UI performance issues. Adding pinData
isn't going to make it terribly worse than it already is.
That said, we need to make the Workflow
class updatable, and update the properties in it, and get rid of this caching code. We can't just keep adding more properties in here.
At some point we need to own this code across packages, and fix it properly.
I've re-opened the ticket to fix this.
|
3 flaky tests on run #5670 ↗︎
Details:
5-ndv.cy.ts • 2 flaky tests
10-undo-redo.cy.ts • 1 flaky test
Review all test suite changes for PR #9693 ↗︎ |
✅ All Cypress E2E specs passed |
@mutdmour Thank you for fixing this. Since I "authored" this PR my review doesn't count for CI, so feel free to merge. |
Thank you @ivov for the review |
Got released with |
Before
After
https://linear.app/n8n/issue/ADO-2111