mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-16 17:46:45 +00:00
perf(editor): Fix log view related slowdown of manual execution with large data (#18256)
This commit is contained in:
@@ -4,12 +4,7 @@ import { Workflow, type IRunExecutionData } from 'n8n-workflow';
|
||||
import { useWorkflowsStore } from '@/stores/workflows.store';
|
||||
import { useNodeHelpers } from '@/composables/useNodeHelpers';
|
||||
import { useThrottleFn } from '@vueuse/core';
|
||||
import {
|
||||
createLogTree,
|
||||
deepToRaw,
|
||||
findSubExecutionLocator,
|
||||
mergeStartData,
|
||||
} from '@/features/logs/logs.utils';
|
||||
import { createLogTree, findSubExecutionLocator, mergeStartData } from '@/features/logs/logs.utils';
|
||||
import { parse } from 'flatted';
|
||||
import { useToast } from '@/composables/useToast';
|
||||
import type { LatestNodeInfo, LogEntry } from '../logs.types';
|
||||
@@ -113,12 +108,10 @@ export function useLogsExecutionData() {
|
||||
execData.value =
|
||||
workflowsStore.workflowExecutionData === null
|
||||
? undefined
|
||||
: deepToRaw(
|
||||
mergeStartData(
|
||||
workflowsStore.workflowExecutionStartedData?.[1] ?? {},
|
||||
workflowsStore.workflowExecutionData,
|
||||
),
|
||||
); // Create deep copy to disable reactivity
|
||||
: mergeStartData(
|
||||
workflowsStore.workflowExecutionStartedData?.[1] ?? {},
|
||||
workflowsStore.workflowExecutionData,
|
||||
);
|
||||
|
||||
if (executionId !== previousExecutionId) {
|
||||
// Reset sub workflow data when top-level execution changes
|
||||
|
||||
@@ -7,7 +7,6 @@ import {
|
||||
} from '@/__tests__/mocks';
|
||||
import {
|
||||
createLogTree,
|
||||
deepToRaw,
|
||||
findSelectedLogEntry,
|
||||
findSubExecutionLocator,
|
||||
getDefaultCollapsedEntries,
|
||||
@@ -27,7 +26,6 @@ import {
|
||||
} from './__test__/data';
|
||||
import type { LogEntrySelection } from './logs.types';
|
||||
import type { IExecutionResponse } from '@/Interface';
|
||||
import { isReactive, reactive } from 'vue';
|
||||
import { createTestLogEntry } from './__test__/mocks';
|
||||
import { AGENT_NODE_TYPE, CHAT_TRIGGER_NODE_TYPE } from '@/constants';
|
||||
|
||||
@@ -1279,29 +1277,6 @@ describe('extractBotResponse', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe(deepToRaw, () => {
|
||||
it('should convert reactive fields to raw in data with circular structure', () => {
|
||||
const data = reactive({
|
||||
foo: reactive({ bar: {} }),
|
||||
bazz: {},
|
||||
});
|
||||
|
||||
data.foo.bar = data;
|
||||
data.bazz = data;
|
||||
|
||||
const raw = deepToRaw(data);
|
||||
|
||||
expect(isReactive(data)).toBe(true);
|
||||
expect(isReactive(data.foo)).toBe(true);
|
||||
expect(isReactive(data.foo.bar)).toBe(true);
|
||||
expect(isReactive(data.bazz)).toBe(true);
|
||||
expect(isReactive(raw)).toBe(false);
|
||||
expect(isReactive(raw.foo)).toBe(false);
|
||||
expect(isReactive(raw.foo.bar)).toBe(false);
|
||||
expect(isReactive(raw.bazz)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe(mergeStartData, () => {
|
||||
it('should return unchanged execution response if start data is empty', () => {
|
||||
const response = createTestWorkflowExecutionResponse({
|
||||
|
||||
@@ -14,7 +14,6 @@ import {
|
||||
type RelatedExecution,
|
||||
} from 'n8n-workflow';
|
||||
import type { LogEntry, LogEntrySelection, LogTreeCreationContext } from './logs.types';
|
||||
import { isProxy, isReactive, isRef, toRaw } from 'vue';
|
||||
import { CHAT_TRIGGER_NODE_TYPE, MANUAL_CHAT_TRIGGER_NODE_TYPE } from '@/constants';
|
||||
import { type ChatMessage } from '@n8n/chat/types';
|
||||
import get from 'lodash/get';
|
||||
@@ -312,44 +311,6 @@ export function findSelectedLogEntry(
|
||||
}
|
||||
}
|
||||
|
||||
export function deepToRaw<T>(sourceObj: T): T {
|
||||
const seen = new WeakMap();
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const objectIterator = (input: any): any => {
|
||||
if (seen.has(input)) {
|
||||
return input;
|
||||
}
|
||||
|
||||
if (input !== null && typeof input === 'object') {
|
||||
seen.set(input, true);
|
||||
}
|
||||
|
||||
if (Array.isArray(input)) {
|
||||
return input.map((item) => objectIterator(item));
|
||||
}
|
||||
|
||||
if (isRef(input) || isReactive(input) || isProxy(input)) {
|
||||
return objectIterator(toRaw(input));
|
||||
}
|
||||
|
||||
if (
|
||||
input !== null &&
|
||||
typeof input === 'object' &&
|
||||
Object.getPrototypeOf(input) === Object.prototype
|
||||
) {
|
||||
return Object.keys(input).reduce((acc, key) => {
|
||||
acc[key as keyof typeof acc] = objectIterator(input[key]);
|
||||
return acc;
|
||||
}, {} as T);
|
||||
}
|
||||
|
||||
return input;
|
||||
};
|
||||
|
||||
return objectIterator(sourceObj);
|
||||
}
|
||||
|
||||
export function flattenLogEntries(
|
||||
entries: LogEntry[],
|
||||
collapsedEntryIds: Record<string, boolean>,
|
||||
|
||||
Reference in New Issue
Block a user