Skip to content

Commit 3c36304

Browse files
committed
Cleanup
1 parent 093e75c commit 3c36304

13 files changed

+106
-73
lines changed

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"packageManager": "[email protected]",
1111
"scripts": {
1212
"preinstall": "node scripts/block-npm-install.js",
13-
"benchmark": "pnpm --filter=n8n benchmark",
13+
"benchmark": "pnpm --filter=n8n benchmark:sqlite",
1414
"build": "turbo run build",
1515
"build:backend": "pnpm --filter=!@n8n/chat --filter=!n8n-design-system --filter=!n8n-editor-ui build",
1616
"build:frontend": "pnpm --filter=@n8n/chat --filter=n8n-design-system --filter=n8n-editor-ui build",

packages/cli/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
"bin": "n8n"
2121
},
2222
"scripts": {
23-
"benchmark": "pnpm build:benchmark && NODE_ENV=benchmark node dist/benchmark/main.js",
23+
"benchmark:sqlite": "pnpm build:benchmark && NODE_ENV=benchmark node dist/benchmark/main.js",
2424
"clean": "rimraf dist .turbo",
2525
"typecheck": "tsc",
2626
"build": "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json && node scripts/build.mjs",

packages/cli/src/benchmark/benchmarks-index.md

-7
This file was deleted.
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Benchmarks
2+
3+
To run benchmarks locally in `cli`:
4+
5+
```sh
6+
pnpm benchmark:sqlite
7+
```
8+
9+
## Creating
10+
11+
To create a benchmark, @TODO
12+
13+
## Listing
14+
15+
### 1. Production workflow with authless webhook node
16+
17+
1.1. using "Respond immediately" mode
18+
1.2. using "When last node finishes" mode
19+
1.3. using "Using 'Respond to Webhook' node" mode
20+
21+
All workflows with default settings.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { ApplicationError } from 'n8n-workflow';
2+
3+
export class UnsupportedDatabaseError extends ApplicationError {
4+
constructor() {
5+
super('Currently only sqlite is supported for benchmarking', { level: 'warning' });
6+
}
7+
}

packages/cli/src/benchmark/lib/global-hooks.ts packages/cli/src/benchmark/lib/hooks.ts

+41-34
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@ import { jsonParse } from 'n8n-workflow';
1313
import { readFile } from 'fs/promises';
1414
import type { WorkflowRequest } from '@/workflows/workflow.request';
1515
import { ActiveWorkflowRunner } from '@/ActiveWorkflowRunner';
16+
import { Logger } from '@/Logger';
1617

18+
/**
19+
* Create a temp `.n8n` dir for encryption key, sqlite DB, etc.
20+
*/
1721
function n8nDir() {
1822
const baseDirPath = path.join(tmpdir(), 'n8n-benchmarks/');
1923

@@ -31,66 +35,69 @@ function n8nDir() {
3135
'utf-8',
3236
);
3337

34-
/**
35-
* @TODO Better approach than overriding? Setting N8N_USER_FOLDER has no effect
36-
*/
38+
// @TODO: Find better approach than overriding like this
39+
// Setting N8N_USER_FOLDER has no effect
3740
const instanceSettings = Container.get(InstanceSettings);
3841
instanceSettings.n8nFolder = _n8nDir;
3942
Container.set(InstanceSettings, instanceSettings);
4043

41-
console.info('.n8n dir', _n8nDir);
44+
Container.get(Logger).info(`Temp .n8n dir location: ${instanceSettings.n8nFolder}`);
4245
}
4346

44-
let main: Start;
45-
46-
async function mainProcess() {
47-
const args: string[] = [];
48-
const _config = new Config({ root: __dirname });
49-
50-
main = new Start(args, _config);
51-
52-
await main.init();
53-
await main.run();
54-
}
55-
56-
async function loadFixtures(owner: User) {
57-
const files = await glob('fixtures/*.json', {
47+
/**
48+
* Load into DB and activate in memory all workflows to use in benchmarks.
49+
*/
50+
async function prepareWorkflows(owner: User) {
51+
const files = await glob('workflows/*.json', {
5852
cwd: path.join('dist', 'benchmark'),
5953
absolute: true,
6054
});
6155

62-
const fixtures: WorkflowRequest.CreatePayload[] = [];
56+
const workflows: WorkflowRequest.CreatePayload[] = [];
6357

6458
for (const file of files) {
6559
const content = await readFile(file, 'utf8');
66-
fixtures.push(jsonParse<WorkflowRequest.CreatePayload>(content));
60+
workflows.push(jsonParse<WorkflowRequest.CreatePayload>(content));
6761
}
6862

69-
for (const fixture of fixtures) {
70-
try {
71-
// @ts-ignore @TODO Fix typing
72-
await Container.get(WorkflowsController).create({ body: fixture, user: owner });
73-
await Container.get(ActiveWorkflowRunner).add(fixture.id as string, 'activate');
74-
} catch (e) {
75-
console.log(e);
76-
}
63+
for (const workflow of workflows) {
64+
// @ts-ignore @TODO Fix typing
65+
await Container.get(WorkflowsController).create({ body: workflow, user: owner });
66+
await Container.get(ActiveWorkflowRunner).add(workflow.id as string, 'activate');
7767
}
68+
}
69+
70+
let main: Start;
7871

79-
// const allActive = await Container.get(WorkflowRepository).getAllActive();
80-
// console.log('allActive', allActive);
72+
/**
73+
* Start the main n8n process to use in benchmarks.
74+
*/
75+
async function mainProcess() {
76+
const args: string[] = [];
77+
const _config = new Config({ root: __dirname });
78+
79+
main = new Start(args, _config);
80+
81+
await main.init();
82+
await main.run();
8183
}
8284

83-
export async function setup() {
85+
/**
86+
* Setup to run before once all benchmarks.
87+
*/
88+
export async function globalSetup() {
8489
n8nDir();
8590

8691
await mainProcess();
87-
// @TODO: Postgres?
8892

8993
const owner = await Container.get(UserRepository).createTestOwner();
9094

91-
await loadFixtures(owner);
95+
await prepareWorkflows(owner);
9296
}
9397

94-
export async function teardown() {
98+
/**
99+
* Teardown to run before after all benchmarks.
100+
*/
101+
export async function globalTeardown() {
95102
await main.stopProcess();
96103
}

packages/cli/src/benchmark/lib/suites.ts

+11-4
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { assert } from 'n8n-workflow';
55
import glob from 'fast-glob';
66
import callsites from 'callsites';
77
import type { Suites, Task, Callback } from './types';
8-
import { DuplicateHookError } from './duplicate-hook.error';
8+
import { DuplicateHookError } from './errors/duplicate-hook.error';
99

1010
export const suites: Suites = {};
1111

@@ -33,7 +33,7 @@ export function registerSuites(bench: Bench) {
3333
* In jest and vitest, `beforeAll` and `afterAll` refer to all tests in a suite,
3434
* while `beforeEach` and `afterEach` refer to each individual test.
3535
*
36-
* The API renames tinybench's hooks to prevent confusion from this difference.
36+
* We rename tinybench's hooks to prevent confusion from this difference.
3737
*/
3838
const options: Record<string, Callback> = {};
3939

@@ -58,16 +58,19 @@ function suiteFilePath() {
5858
}
5959

6060
/**
61-
* Benchmarking API
61+
* Run a benchmarking task, i.e. a single operation whose performance to measure.
6262
*/
63-
6463
export function task(description: string, operation: Task['operation']) {
6564
const filePath = suiteFilePath();
6665

6766
suites[filePath] ||= { hooks: {}, tasks: [] };
6867
suites[filePath].tasks.push({ description, operation });
6968
}
7069

70+
/**
71+
* Setup step to run once before each benchmarking task in a suite.
72+
* Only one `beforeEach` is allowed per suite.
73+
*/
7174
export function beforeEach(fn: Callback) {
7275
const filePath = suiteFilePath();
7376

@@ -79,6 +82,10 @@ export function beforeEach(fn: Callback) {
7982
suites[filePath].hooks.beforeEach = fn;
8083
}
8184

85+
/**
86+
* Teardown step to run once after each benchmarking task in a suite.
87+
* Only one `afterEach` is allowed per suite.
88+
*/
8289
export function afterEach(fn: Callback) {
8390
const filePath = suiteFilePath();
8491

packages/cli/src/benchmark/lib/types.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
/**
2+
* Benchmarking suites, i.e. `*.tasks.ts` files containing benchmarking tasks.
3+
*/
14
export type Suites = {
25
[suiteFilepath: string]: {
36
hooks: {
@@ -8,7 +11,9 @@ export type Suites = {
811
};
912
};
1013

11-
/** A benchmarking task, i.e. a single operation whose performance to measure. */
14+
/**
15+
* A benchmarking task, i.e. a single operation whose performance to measure.
16+
*/
1217
export type Task = {
1318
description: string;
1419
operation: Callback;

packages/cli/src/benchmark/main.ts

+17-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import 'reflect-metadata';
2-
import * as globalHooks from './lib/global-hooks';
2+
import * as hooks from './lib/hooks';
33
import { collectSuites, registerSuites, suiteCount } from './lib/suites';
4+
import config from '@/config';
5+
import { UnsupportedDatabaseError } from './lib/errors/unsupported-database.error';
6+
import { Logger } from '@/Logger';
7+
import Container from 'typedi';
48

59
/* eslint-disable import/no-extraneous-dependencies */
610
import Bench from 'tinybench';
@@ -10,16 +14,24 @@ import { withCodSpeed } from '@codspeed/tinybench-plugin';
1014
export { beforeEach, afterEach, task } from './lib/suites';
1115

1216
async function main() {
17+
const dbType = config.getEnv('database.type');
18+
19+
if (dbType !== 'sqlite') throw new UnsupportedDatabaseError();
20+
1321
await collectSuites();
1422

1523
const count = suiteCount();
1624

25+
const logger = Container.get(Logger);
26+
1727
if (count === 0) {
18-
console.log('No benchmarking suites found');
28+
logger.info('No benchmarking suites found. Exiting...');
1929
return;
2030
}
2131

22-
await globalHooks.setup();
32+
logger.info(`Running ${count} benchmarking ${count === 1 ? 'suite' : 'suites'}...`);
33+
34+
await hooks.globalSetup();
2335

2436
const _bench = new Bench({
2537
time: 0, // @TODO: Temp value
@@ -30,13 +42,11 @@ async function main() {
3042

3143
registerSuites(bench);
3244

33-
console.log(`Running ${count} benchmarking suites...`);
34-
3545
await bench.run();
3646

37-
console.table(bench.table());
47+
console.table(bench.table()); // @TODO: Output properly? Ref. Codspeed
3848

39-
await globalHooks.teardown();
49+
await hooks.globalTeardown();
4050
}
4151

4252
void main();

packages/cli/src/benchmark/tasks/example.tasks.ts

-17
This file was deleted.

packages/cli/tsconfig.benchmark.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@
55
"outDir": "dist",
66
"tsBuildInfoFile": "dist/benchmark.tsbuildinfo"
77
},
8-
"include": ["src/**/*.ts", "src/benchmark/**/*.ts", "src/benchmark/fixtures/*.json"],
8+
"include": ["src/**/*.ts", "src/benchmark/**/*.ts", "src/benchmark/workflows/*.json"],
99
"exclude": ["test/**"]
1010
}

0 commit comments

Comments
 (0)