n8n/packages/testing/performance/benchmarks/expression-engine/fixtures/data.ts
Iván Ovejero f8c21276cb
feat(core): Make VM expression bridge timeout and memory limit configurable (#27962)
Co-authored-by: Danny Martini <danny@n8n.io>
2026-04-08 16:07:16 +00:00

157 lines
3.2 KiB
TypeScript

import { Workflow, Expression } from 'n8n-workflow';
import type { INodeTypes, INodeType, INodeTypeDescription, INodeExecutionData } from 'n8n-workflow';
// Minimal node types for workflow instantiation
class TestNodeTypes implements INodeTypes {
getByName(nodeType: string): INodeType {
return {
description: {
name: nodeType,
displayName: 'Test',
group: ['transform'],
version: 1,
defaults: { name: 'Test' },
inputs: ['main'],
outputs: ['main'],
properties: [],
description: '',
} as INodeTypeDescription,
execute: async () => [[{ json: {} }]],
};
}
getByNameAndVersion(): INodeType {
return this.getByName('test.set');
}
getKnownTypes(): Record<string, Record<string, unknown>> {
return {};
}
}
// ── Workflow factory ──
const nodeTypes = new TestNodeTypes();
export function createWorkflow(): Workflow {
return new Workflow({
id: '1',
nodes: [
{
name: 'node',
typeVersion: 1,
type: 'test.set',
id: 'uuid-1234',
position: [0, 0],
parameters: {},
},
{
name: 'HTTP Request',
typeVersion: 1,
type: 'test.set',
id: 'uuid-5678',
position: [100, 0],
parameters: {},
},
],
connections: {},
active: false,
nodeTypes,
});
}
// ── Evaluate helper ──
export function evaluate(workflow: Workflow, expr: string, data: INodeExecutionData[]): unknown {
return workflow.expression.getParameterValue(expr, null, 0, 0, 'node', data, 'manual', {});
}
// ── Data generators ──
export function makeSmallData(): INodeExecutionData[] {
return [
{
json: {
id: 123,
name: 'John Doe',
email: 'john@example.com',
status: 'active',
date: '2026-03-02T12:00:00.000Z',
nested: {
user: {
profile: {
displayName: 'johndoe',
age: 30,
},
},
},
},
},
];
}
export function makeMediumData(): INodeExecutionData[] {
return [
{
json: {
id: 1,
name: 'Batch Result',
items: Array.from({ length: 100 }, (_, i) => ({
id: i,
value: i * 10,
active: i % 2 === 0,
label: `item-${i}`,
user: {
name: `User ${i}`,
email: `user${i}@example.com`,
},
})),
},
},
];
}
export function makeLargeData(): INodeExecutionData[] {
return [
{
json: {
id: 1,
name: 'Large Batch',
items: Array.from({ length: 10_000 }, (_, i) => ({
id: i,
value: i * 10,
active: i % 2 === 0,
label: `item-${i}`,
user: {
name: `User ${i}`,
profile: {
age: 20 + (i % 50),
city: `City ${i % 100}`,
},
},
})),
},
},
];
}
// ── Engine switching helpers ──
export async function useLegacyEngine(): Promise<void> {
await Expression.disposeExpressionEngine();
Expression.setExpressionEngine('legacy');
}
export async function useVmEngine(): Promise<void> {
// Use a higher timeout for benchmarks — CodSpeed's instruction-counting
// instrumentation adds significant wall-clock overhead that can cause the
// default 5s timeout to fire on larger data set benchmarks (e.g. 10k items).
await Expression.initExpressionEngine({
engine: 'vm',
poolSize: 1,
maxCodeCacheSize: 1024,
bridgeTimeout: 60_000,
bridgeMemoryLimit: 128,
});
}