refactor(core): Persist node execution order, and forward it to the frontend (#14455)

This commit is contained in:
कारतोफ्फेलस्क्रिप्ट™
2025-04-09 10:19:58 +02:00
committed by GitHub
parent 707ecb63ae
commit 9ba58ca80b
41 changed files with 235 additions and 113 deletions

View File

@@ -256,6 +256,7 @@ describe('CanvasChat', () => {
],
],
},
executionIndex: 0,
executionStatus: 'success',
executionTime: 0,
source: [null],

View File

@@ -71,7 +71,8 @@ export const aiChatExecutionResponse: IExecutionResponse = {
'AI Agent': [
{
executionStatus: 'success',
startTime: +new Date('2025-03-26T00:00:00.002Z'),
startTime: Date.parse('2025-03-26T00:00:00.002Z'),
executionIndex: 0,
executionTime: 1778,
source: [],
data: {},
@@ -80,7 +81,8 @@ export const aiChatExecutionResponse: IExecutionResponse = {
'AI Model': [
{
executionStatus: 'error',
startTime: +new Date('2025-03-26T00:00:00.003Z'),
startTime: Date.parse('2025-03-26T00:00:00.003Z'),
executionIndex: 1,
executionTime: 1777,
source: [],
error: new WorkflowOperationError('Test error', aiModelNode, 'Test error description'),
@@ -121,7 +123,8 @@ export const aiManualExecutionResponse: IExecutionResponse = {
'AI Agent': [
{
executionStatus: 'success',
startTime: +new Date('2025-03-30T00:00:00.002Z'),
startTime: Date.parse('2025-03-30T00:00:00.002Z'),
executionIndex: 0,
executionTime: 12,
source: [],
data: {},
@@ -130,7 +133,8 @@ export const aiManualExecutionResponse: IExecutionResponse = {
'AI Model': [
{
executionStatus: 'success',
startTime: +new Date('2025-03-30T00:00:00.003Z'),
startTime: Date.parse('2025-03-30T00:00:00.003Z'),
executionIndex: 1,
executionTime: 3456,
source: [],
data: {

View File

@@ -130,8 +130,9 @@ export function useChatMessaging({
inputPayload.binary = binaryData;
}
const nodeData: ITaskData = {
startTime: new Date().getTime(),
startTime: Date.now(),
executionTime: 0,
executionIndex: 0,
executionStatus: 'success',
data: {
main: [[inputPayload]],

View File

@@ -128,6 +128,7 @@ describe('InputPanel', () => {
{
startTime: 0,
executionTime: 0,
executionIndex: 0,
source: [],
data: {},
},

View File

@@ -359,8 +359,9 @@ describe('RunData', () => {
const { getByTestId, queryByTestId } = render({
runs: [
{
startTime: new Date().getTime(),
executionTime: new Date().getTime(),
startTime: Date.now(),
executionIndex: 0,
executionTime: 1,
data: {
main: [[{ json: {} }]],
},
@@ -368,8 +369,9 @@ describe('RunData', () => {
metadata,
},
{
startTime: new Date().getTime(),
executionTime: new Date().getTime(),
startTime: Date.now(),
executionIndex: 1,
executionTime: 1,
data: {
main: [[{ json: {} }]],
},
@@ -413,6 +415,7 @@ describe('RunData', () => {
{
hints: [],
startTime: 1737643696893,
executionIndex: 0,
executionTime: 2,
source: [
{
@@ -598,8 +601,9 @@ describe('RunData', () => {
runs?: ITaskData[];
}) => {
const defaultRun: ITaskData = {
startTime: new Date().getTime(),
executionTime: new Date().getTime(),
startTime: Date.now(),
executionIndex: 0,
executionTime: 1,
data: {
main: [defaultRunItems ?? [{ json: {} }]],
},

View File

@@ -6,6 +6,7 @@ describe(getTreeNodeData, () => {
function createTaskData(partialData: Partial<ITaskData>): ITaskData {
return {
startTime: 0,
executionIndex: 0,
executionTime: 1,
source: [],
executionStatus: 'success',
@@ -29,10 +30,10 @@ describe(getTreeNodeData, () => {
},
});
const taskDataByNodeName: Record<string, ITaskData[]> = {
A: [createTaskData({ startTime: +new Date('2025-02-26T00:00:00.000Z') })],
A: [createTaskData({ startTime: Date.parse('2025-02-26T00:00:00.000Z') })],
B: [
createTaskData({
startTime: +new Date('2025-02-26T00:00:01.000Z'),
startTime: Date.parse('2025-02-26T00:00:01.000Z'),
data: {
main: [
[
@@ -50,7 +51,7 @@ describe(getTreeNodeData, () => {
},
}),
createTaskData({
startTime: +new Date('2025-02-26T00:00:03.000Z'),
startTime: Date.parse('2025-02-26T00:00:03.000Z'),
data: {
main: [
[
@@ -70,7 +71,7 @@ describe(getTreeNodeData, () => {
],
C: [
createTaskData({
startTime: +new Date('2025-02-26T00:00:02.000Z'),
startTime: Date.parse('2025-02-26T00:00:02.000Z'),
data: {
main: [
[
@@ -87,7 +88,7 @@ describe(getTreeNodeData, () => {
],
},
}),
createTaskData({ startTime: +new Date('2025-02-26T00:00:04.000Z') }),
createTaskData({ startTime: Date.parse('2025-02-26T00:00:04.000Z') }),
],
};
@@ -117,7 +118,7 @@ describe(getTreeNodeData, () => {
id: 'B',
node: 'B',
runIndex: 0,
startTime: +new Date('2025-02-26T00:00:01.000Z'),
startTime: Date.parse('2025-02-26T00:00:01.000Z'),
parent: expect.objectContaining({ node: 'A' }),
consumedTokens: {
completionTokens: 1,
@@ -132,7 +133,7 @@ describe(getTreeNodeData, () => {
id: 'C',
node: 'C',
runIndex: 0,
startTime: +new Date('2025-02-26T00:00:02.000Z'),
startTime: Date.parse('2025-02-26T00:00:02.000Z'),
parent: expect.objectContaining({ node: 'B' }),
consumedTokens: {
completionTokens: 7,
@@ -148,7 +149,7 @@ describe(getTreeNodeData, () => {
id: 'B',
node: 'B',
runIndex: 1,
startTime: +new Date('2025-02-26T00:00:03.000Z'),
startTime: Date.parse('2025-02-26T00:00:03.000Z'),
parent: expect.objectContaining({ node: 'A' }),
consumedTokens: {
completionTokens: 4,
@@ -163,7 +164,7 @@ describe(getTreeNodeData, () => {
id: 'C',
node: 'C',
runIndex: 1,
startTime: +new Date('2025-02-26T00:00:04.000Z'),
startTime: Date.parse('2025-02-26T00:00:04.000Z'),
parent: expect.objectContaining({ node: 'B' }),
consumedTokens: {
completionTokens: 0,

View File

@@ -68,8 +68,9 @@ async function createPiniaWithActiveNode() {
runData: {
[node.name]: [
{
startTime: new Date().getTime(),
executionTime: new Date().getTime(),
startTime: Date.now(),
executionIndex: 0,
executionTime: 1,
data: {
main: [
[
@@ -91,8 +92,9 @@ async function createPiniaWithActiveNode() {
source: [null],
},
{
startTime: new Date().getTime(),
executionTime: new Date().getTime(),
startTime: Date.now(),
executionIndex: 1,
executionTime: 1,
data: {
main: [
[

View File

@@ -278,6 +278,7 @@ export const SUPPORT_CHAT_TEST_PAYLOAD: ChatRequest.RequestPayload = {
{
hints: [],
startTime: 1737540693122,
executionIndex: 0,
executionTime: 1,
source: [],
executionStatus: 'success',
@@ -287,6 +288,7 @@ export const SUPPORT_CHAT_TEST_PAYLOAD: ChatRequest.RequestPayload = {
{
hints: [],
startTime: 1737540693124,
executionIndex: 1,
executionTime: 2,
source: [
{
@@ -300,6 +302,7 @@ export const SUPPORT_CHAT_TEST_PAYLOAD: ChatRequest.RequestPayload = {
{
hints: [],
startTime: 1737540693126,
executionIndex: 2,
executionTime: 0,
source: [
{
@@ -313,6 +316,7 @@ export const SUPPORT_CHAT_TEST_PAYLOAD: ChatRequest.RequestPayload = {
{
hints: [],
startTime: 1737540693127,
executionIndex: 3,
executionTime: 0,
source: [
{
@@ -326,6 +330,7 @@ export const SUPPORT_CHAT_TEST_PAYLOAD: ChatRequest.RequestPayload = {
{
hints: [],
startTime: 1737540693127,
executionIndex: 4,
executionTime: 28,
source: [
{

View File

@@ -460,6 +460,7 @@ const testExecutionData: IRunExecutionData['resultData'] = {
{
hints: [],
startTime: 1732882780588,
executionIndex: 0,
executionTime: 4,
source: [],
executionStatus: 'success',
@@ -481,6 +482,7 @@ const testExecutionData: IRunExecutionData['resultData'] = {
{
hints: [],
startTime: 1732882780593,
executionIndex: 1,
executionTime: 0,
source: [
{

View File

@@ -400,6 +400,7 @@ describe('useCanvasMapping', () => {
{
startTime: 0,
executionTime: 0,
executionIndex: 0,
source: [],
data: {
[NodeConnectionTypes.Main]: [[{ json: {} }, { json: {} }]],
@@ -443,6 +444,7 @@ describe('useCanvasMapping', () => {
{
startTime: 0,
executionTime: 0,
executionIndex: 0,
source: [],
data: {
[NodeConnectionTypes.Main]: [[{ json: {} }]],
@@ -455,6 +457,7 @@ describe('useCanvasMapping', () => {
{
startTime: 0,
executionTime: 0,
executionIndex: 0,
source: [],
data: {
[NodeConnectionTypes.Main]: [[{ json: {} }, { json: {} }, { json: {} }]],
@@ -511,6 +514,7 @@ describe('useCanvasMapping', () => {
{
startTime: 0,
executionTime: 0,
executionIndex: 0,
source: [],
data: {
[NodeConnectionTypes.Main]: [[{ json: {} }]],
@@ -519,6 +523,7 @@ describe('useCanvasMapping', () => {
{
startTime: 0,
executionTime: 0,
executionIndex: 1,
source: [],
data: {
[NodeConnectionTypes.Main]: [[{ json: {} }, { json: {} }, { json: {} }]],
@@ -527,6 +532,7 @@ describe('useCanvasMapping', () => {
{
startTime: 0,
executionTime: 0,
executionIndex: 2,
source: [],
data: {
[NodeConnectionTypes.Main]: [[{ json: {} }, { json: {} }]],
@@ -722,6 +728,7 @@ describe('useCanvasMapping', () => {
{
startTime: 0,
executionTime: 0,
executionIndex: 0,
source: [],
error: mock<NodeApiError>({
message: errorMessage,
@@ -753,6 +760,7 @@ describe('useCanvasMapping', () => {
{
startTime: 0,
executionTime: 0,
executionIndex: 0,
source: [],
error: mock<NodeApiError>({
message: errorMessage,
@@ -783,6 +791,7 @@ describe('useCanvasMapping', () => {
{
startTime: 0,
executionTime: 0,
executionIndex: 0,
source: [],
error: mock<NodeApiError>({
message: 'Error 1',
@@ -792,6 +801,7 @@ describe('useCanvasMapping', () => {
{
startTime: 0,
executionTime: 0,
executionIndex: 1,
source: [],
error: mock<NodeApiError>({
message: 'Error 2',
@@ -855,6 +865,7 @@ describe('useCanvasMapping', () => {
{
startTime: 0,
executionTime: 0,
executionIndex: 0,
source: [],
error: mock<NodeApiError>({
message: 'Execution error',
@@ -894,6 +905,7 @@ describe('useCanvasMapping', () => {
{
startTime: 0,
executionTime: 0,
executionIndex: 0,
source: [],
error: mock<NodeApiError>({
message: 'Execution error',
@@ -948,6 +960,7 @@ describe('useCanvasMapping', () => {
{
startTime: 0,
executionTime: 0,
executionIndex: 0,
source: [],
executionStatus: 'crashed',
},
@@ -976,6 +989,7 @@ describe('useCanvasMapping', () => {
{
startTime: 0,
executionTime: 0,
executionIndex: 0,
source: [],
executionStatus: 'error',
},
@@ -1057,6 +1071,7 @@ describe('useCanvasMapping', () => {
{
startTime: 0,
executionTime: 0,
executionIndex: 0,
source: [],
executionStatus: 'error',
error: mock<NodeApiError>({
@@ -1096,6 +1111,7 @@ describe('useCanvasMapping', () => {
{
startTime: 0,
executionTime: 0,
executionIndex: 0,
source: [],
executionStatus: 'error',
},
@@ -1104,6 +1120,7 @@ describe('useCanvasMapping', () => {
{
startTime: 0,
executionTime: 0,
executionIndex: 0,
source: [],
executionStatus: 'success',
},

View File

@@ -553,7 +553,9 @@ describe('useDataSchema', () => {
data: {
resultData: {
runData: {
[runDataKey ?? name]: [{ data, startTime: 0, executionTime: 0, source: [] }],
[runDataKey ?? name]: [
{ data, startTime: 0, executionTime: 0, executionIndex: 0, source: [] },
],
},
},
},
@@ -619,17 +621,20 @@ describe('useDataSchema', () => {
{
startTime: 0,
executionTime: 0,
executionIndex: 0,
source: [],
},
{
startTime: 0,
executionTime: 0,
executionIndex: 1,
source: [],
},
{
data: { [Main]: [null, mockExecutionDataMarker] },
startTime: 0,
executionTime: 0,
executionIndex: 2,
source: [],
},
],

View File

@@ -156,6 +156,7 @@ describe(useNodeDirtiness, () => {
{
startTime: +runAt,
executionTime: 0,
executionIndex: 0,
executionStatus: 'success',
source: [],
},
@@ -423,6 +424,7 @@ describe(useNodeDirtiness, () => {
{
startTime: +NODE_RUN_AT,
executionTime: 0,
executionIndex: 0,
executionStatus: 'success',
source: [],
},

View File

@@ -354,6 +354,7 @@ describe('useRunWorkflow({ router })', () => {
[parentName]: [
{
startTime: 1,
executionIndex: 0,
executionTime: 0,
source: [],
},
@@ -361,6 +362,7 @@ describe('useRunWorkflow({ router })', () => {
[executeName]: [
{
startTime: 1,
executionIndex: 1,
executionTime: 8,
source: [
{

View File

@@ -9,6 +9,7 @@ const runExecutionData: IRunExecutionData = {
Start: [
{
startTime: 1,
executionIndex: 0,
executionTime: 1,
data: {
main: [
@@ -25,6 +26,7 @@ const runExecutionData: IRunExecutionData = {
Function: [
{
startTime: 1,
executionIndex: 1,
executionTime: 1,
data: {
main: [
@@ -62,6 +64,7 @@ const runExecutionData: IRunExecutionData = {
Rename: [
{
startTime: 1,
executionIndex: 2,
executionTime: 1,
data: {
main: [
@@ -99,6 +102,7 @@ const runExecutionData: IRunExecutionData = {
End: [
{
startTime: 1,
executionIndex: 3,
executionTime: 1,
data: {
main: [

View File

@@ -849,6 +849,7 @@ function generateMockExecutionEvents() {
data: {
hints: [],
startTime: 1727867966633,
executionIndex: 0,
executionTime: 1,
source: [],
executionStatus: 'success',
@@ -873,6 +874,7 @@ function generateMockExecutionEvents() {
data: {
hints: [],
startTime: 1727869043441,
executionIndex: 0,
executionTime: 2,
source: [
{

View File

@@ -15,6 +15,7 @@ const MOCK_EXECUTION: Partial<IExecutionResponse> = {
'When clicking Test workflow': [
{
startTime: 1706027170005,
executionIndex: 0,
executionTime: 0,
source: [],
executionStatus: 'success',
@@ -24,6 +25,7 @@ const MOCK_EXECUTION: Partial<IExecutionResponse> = {
DebugHelper: [
{
startTime: 1706027170005,
executionIndex: 1,
executionTime: 1,
source: [{ previousNode: 'When clicking Test workflow' }],
executionStatus: 'success',
@@ -58,6 +60,7 @@ const MOCK_EXECUTION: Partial<IExecutionResponse> = {
If: [
{
startTime: 1706027170006,
executionIndex: 2,
executionTime: 1,
source: [{ previousNode: 'DebugHelper' }],
executionStatus: 'success',
@@ -94,6 +97,7 @@ const MOCK_EXECUTION: Partial<IExecutionResponse> = {
'Edit Fields': [
{
startTime: 1706027170008,
executionIndex: 3,
executionTime: 0,
source: [{ previousNode: 'If', previousNodeOutput: 1 }],
executionStatus: 'success',
@@ -116,6 +120,7 @@ const MOCK_EXECUTION: Partial<IExecutionResponse> = {
},
{
startTime: 1706027170009,
executionIndex: 3,
executionTime: 0,
source: [{ previousNode: 'If' }],
executionStatus: 'success',
@@ -140,6 +145,7 @@ const MOCK_EXECUTION: Partial<IExecutionResponse> = {
'Edit Fields1': [
{
startTime: 1706027170008,
executionIndex: 4,
executionTime: 0,
source: [{ previousNode: 'Edit Fields' }],
executionStatus: 'success',
@@ -162,6 +168,7 @@ const MOCK_EXECUTION: Partial<IExecutionResponse> = {
},
{
startTime: 1706027170010,
executionIndex: 5,
executionTime: 0,
source: [{ previousNode: 'Edit Fields', previousNodeRun: 1 }],
executionStatus: 'success',
@@ -329,6 +336,7 @@ describe('pairedItemUtils', () => {
Start: [
{
startTime: 1706027170005,
executionIndex: 0,
executionTime: 0,
source: [],
executionStatus: 'success',
@@ -340,6 +348,7 @@ describe('pairedItemUtils', () => {
DebugHelper: [
{
startTime: 1706027170005,
executionIndex: 1,
executionTime: 1,
source: [{ previousNode: 'Start' }],
executionStatus: 'success',
@@ -409,8 +418,9 @@ describe('pairedItemUtils', () => {
runData: Object.fromEntries(
Array.from({ length: nodeCount }).map<[string, ITaskData[]]>((_, j) => [
`node_${j}`,
Array.from({ length: runCount }).map(() => ({
Array.from({ length: runCount }).map((_, executionIndex) => ({
startTime: 1706027170005,
executionIndex,
executionTime: 0,
source: j === 0 ? [] : [{ previousNode: `node_${j - 1}` }],
executionStatus: 'success',