@atom8n/n8n-benchmark 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +4 -0
- package/Dockerfile +63 -0
- package/README.md +122 -0
- package/bin/n8n-benchmark +13 -0
- package/biome.jsonc +7 -0
- package/dist/build.tsbuildinfo +1 -0
- package/dist/commands/list.d.ts +8 -0
- package/dist/commands/list.js +23 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/run.d.ts +24 -0
- package/dist/commands/run.js +128 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/config/common-flags.d.ts +1 -0
- package/dist/config/common-flags.js +9 -0
- package/dist/config/common-flags.js.map +1 -0
- package/dist/n8n-api-client/authenticated-n8n-api-client.d.ts +15 -0
- package/dist/n8n-api-client/authenticated-n8n-api-client.js +67 -0
- package/dist/n8n-api-client/authenticated-n8n-api-client.js.map +1 -0
- package/dist/n8n-api-client/credentials-api-client.d.ts +9 -0
- package/dist/n8n-api-client/credentials-api-client.js +24 -0
- package/dist/n8n-api-client/credentials-api-client.js.map +1 -0
- package/dist/n8n-api-client/data-table-api-client.d.ts +9 -0
- package/dist/n8n-api-client/data-table-api-client.js +23 -0
- package/dist/n8n-api-client/data-table-api-client.js.map +1 -0
- package/dist/n8n-api-client/n8n-api-client.d.ts +13 -0
- package/dist/n8n-api-client/n8n-api-client.js +82 -0
- package/dist/n8n-api-client/n8n-api-client.js.map +1 -0
- package/dist/n8n-api-client/n8n-api-client.types.d.ts +21 -0
- package/dist/n8n-api-client/n8n-api-client.types.js +3 -0
- package/dist/n8n-api-client/n8n-api-client.types.js.map +1 -0
- package/dist/n8n-api-client/project-api-client.d.ts +6 -0
- package/dist/n8n-api-client/project-api-client.js +14 -0
- package/dist/n8n-api-client/project-api-client.js.map +1 -0
- package/dist/n8n-api-client/workflows-api-client.d.ts +11 -0
- package/dist/n8n-api-client/workflows-api-client.js +30 -0
- package/dist/n8n-api-client/workflows-api-client.js.map +1 -0
- package/dist/scenario/scenario-data-loader.d.ts +13 -0
- package/dist/scenario/scenario-data-loader.js +84 -0
- package/dist/scenario/scenario-data-loader.js.map +1 -0
- package/dist/scenario/scenario-loader.d.ts +7 -0
- package/dist/scenario/scenario-loader.js +101 -0
- package/dist/scenario/scenario-loader.js.map +1 -0
- package/dist/test-execution/app-metrics-poller.d.ts +13 -0
- package/dist/test-execution/app-metrics-poller.js +54 -0
- package/dist/test-execution/app-metrics-poller.js.map +1 -0
- package/dist/test-execution/k6-executor.d.ts +33 -0
- package/dist/test-execution/k6-executor.js +120 -0
- package/dist/test-execution/k6-executor.js.map +1 -0
- package/dist/test-execution/k6-summary.d.ts +82 -0
- package/dist/test-execution/k6-summary.js +2 -0
- package/dist/test-execution/k6-summary.js.map +1 -0
- package/dist/test-execution/prometheus-metrics-parser.d.ts +9 -0
- package/dist/test-execution/prometheus-metrics-parser.js +44 -0
- package/dist/test-execution/prometheus-metrics-parser.js.map +1 -0
- package/dist/test-execution/scenario-data-importer.d.ts +21 -0
- package/dist/test-execution/scenario-data-importer.js +108 -0
- package/dist/test-execution/scenario-data-importer.js.map +1 -0
- package/dist/test-execution/scenario-runner.d.ts +18 -0
- package/dist/test-execution/scenario-runner.js +46 -0
- package/dist/test-execution/scenario-runner.js.map +1 -0
- package/dist/test-execution/test-report.d.ts +56 -0
- package/dist/test-execution/test-report.js +65 -0
- package/dist/test-execution/test-report.js.map +1 -0
- package/dist/types/scenario.d.ts +16 -0
- package/dist/types/scenario.js +3 -0
- package/dist/types/scenario.js.map +1 -0
- package/eslint.config.mjs +22 -0
- package/infra/.terraform.lock.hcl +60 -0
- package/infra/benchmark-env.tf +54 -0
- package/infra/modules/benchmark-vm/output.tf +11 -0
- package/infra/modules/benchmark-vm/vars.tf +29 -0
- package/infra/modules/benchmark-vm/vm.tf +126 -0
- package/infra/output.tf +16 -0
- package/infra/providers.tf +23 -0
- package/infra/vars.tf +34 -0
- package/package.json +55 -0
- package/scenarios/binary-data/binary-data.json +67 -0
- package/scenarios/binary-data/binary-data.manifest.json +7 -0
- package/scenarios/binary-data/binary-data.script.js +29 -0
- package/scenarios/credential-http-node/credential-bearer.json +8 -0
- package/scenarios/credential-http-node/credential-http-node.json +241 -0
- package/scenarios/credential-http-node/credential-http-node.manifest.json +10 -0
- package/scenarios/credential-http-node/credential-http-node.script.js +30 -0
- package/scenarios/data-table-node/data-table-node.json +168 -0
- package/scenarios/data-table-node/data-table-node.manifest.json +10 -0
- package/scenarios/data-table-node/data-table-node.script.js +38 -0
- package/scenarios/data-table-node/data-table.json +25 -0
- package/scenarios/http-node/http-node.json +213 -0
- package/scenarios/http-node/http-node.manifest.json +7 -0
- package/scenarios/http-node/http-node.script.js +30 -0
- package/scenarios/js-code-node/js-code-node.json +96 -0
- package/scenarios/js-code-node/js-code-node.manifest.json +7 -0
- package/scenarios/js-code-node/js-code-node.script.js +29 -0
- package/scenarios/multiple-webhooks/multiple-webhooks.manifest.json +20 -0
- package/scenarios/multiple-webhooks/multiple-webhooks.script.js +19 -0
- package/scenarios/multiple-webhooks/multiple-webhooks1.json +25 -0
- package/scenarios/multiple-webhooks/multiple-webhooks10.json +25 -0
- package/scenarios/multiple-webhooks/multiple-webhooks2.json +25 -0
- package/scenarios/multiple-webhooks/multiple-webhooks3.json +25 -0
- package/scenarios/multiple-webhooks/multiple-webhooks4.json +25 -0
- package/scenarios/multiple-webhooks/multiple-webhooks5.json +25 -0
- package/scenarios/multiple-webhooks/multiple-webhooks6.json +25 -0
- package/scenarios/multiple-webhooks/multiple-webhooks7.json +25 -0
- package/scenarios/multiple-webhooks/multiple-webhooks8.json +25 -0
- package/scenarios/multiple-webhooks/multiple-webhooks9.json +25 -0
- package/scenarios/py-code-node/py-code-node.json +98 -0
- package/scenarios/py-code-node/py-code-node.manifest.json +7 -0
- package/scenarios/py-code-node/py-code-node.script.js +29 -0
- package/scenarios/scenario.schema.json +51 -0
- package/scenarios/set-node-expressions/set-node-expressions.json +91 -0
- package/scenarios/set-node-expressions/set-node-expressions.manifest.json +7 -0
- package/scenarios/set-node-expressions/set-node-expressions.script.js +18 -0
- package/scenarios/single-webhook/single-webhook.json +25 -0
- package/scenarios/single-webhook/single-webhook.manifest.json +7 -0
- package/scenarios/single-webhook/single-webhook.script.js +18 -0
- package/scripts/bootstrap.sh +63 -0
- package/scripts/clients/docker-compose-client.mjs +45 -0
- package/scripts/clients/ssh-client.mjs +37 -0
- package/scripts/clients/terraform-client.mjs +71 -0
- package/scripts/destroy-cloud-env.mjs +86 -0
- package/scripts/mock-api/mappings/mockApiData.json +92110 -0
- package/scripts/n8n-setups/postgres/docker-compose.yml +76 -0
- package/scripts/n8n-setups/postgres/setup.mjs +15 -0
- package/scripts/n8n-setups/scaling-multi-main/docker-compose.yml +230 -0
- package/scripts/n8n-setups/scaling-multi-main/nginx.conf +24 -0
- package/scripts/n8n-setups/scaling-multi-main/setup.mjs +15 -0
- package/scripts/n8n-setups/scaling-single-main/docker-compose.yml +174 -0
- package/scripts/n8n-setups/scaling-single-main/setup.mjs +15 -0
- package/scripts/n8n-setups/sqlite/docker-compose.yml +55 -0
- package/scripts/n8n-setups/sqlite/setup.mjs +15 -0
- package/scripts/provision-cloud-env.mjs +36 -0
- package/scripts/run-for-n8n-setup.mjs +175 -0
- package/scripts/run-in-cloud.mjs +167 -0
- package/scripts/run-locally.mjs +73 -0
- package/scripts/run.mjs +192 -0
- package/scripts/utils/flags.mjs +20 -0
- package/src/commands/list.ts +26 -0
- package/src/commands/run.ts +140 -0
- package/src/config/common-flags.ts +6 -0
- package/src/n8n-api-client/authenticated-n8n-api-client.ts +88 -0
- package/src/n8n-api-client/credentials-api-client.ts +28 -0
- package/src/n8n-api-client/data-table-api-client.ts +30 -0
- package/src/n8n-api-client/n8n-api-client.ts +85 -0
- package/src/n8n-api-client/n8n-api-client.types.ts +27 -0
- package/src/n8n-api-client/project-api-client.ts +11 -0
- package/src/n8n-api-client/workflows-api-client.ts +38 -0
- package/src/scenario/scenario-data-loader.ts +75 -0
- package/src/scenario/scenario-loader.ts +90 -0
- package/src/test-execution/app-metrics-poller.ts +81 -0
- package/src/test-execution/k6-executor.ts +192 -0
- package/src/test-execution/k6-summary.ts +255 -0
- package/src/test-execution/prometheus-metrics-parser.ts +63 -0
- package/src/test-execution/scenario-data-importer.ts +165 -0
- package/src/test-execution/scenario-runner.ts +76 -0
- package/src/test-execution/test-report.ts +152 -0
- package/src/types/scenario.ts +33 -0
- package/tsconfig.build.json +9 -0
- package/tsconfig.json +14 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildAppMetricsReport = buildAppMetricsReport;
|
|
4
|
+
exports.buildTestReport = buildTestReport;
|
|
5
|
+
const nanoid_1 = require("nanoid");
|
|
6
|
+
const prometheus_metrics_parser_1 = require("../test-execution/prometheus-metrics-parser");
|
|
7
|
+
function k6CheckToCheck(check) {
|
|
8
|
+
return {
|
|
9
|
+
name: check.name,
|
|
10
|
+
passes: check.passes,
|
|
11
|
+
fails: check.fails,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
function k6CounterToCounter(counter) {
|
|
15
|
+
return {
|
|
16
|
+
type: 'counter',
|
|
17
|
+
count: counter.values.count,
|
|
18
|
+
rate: counter.values.rate,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
function k6TrendToTrend(trend) {
|
|
22
|
+
return {
|
|
23
|
+
type: 'trend',
|
|
24
|
+
'p(90)': trend.values['p(90)'],
|
|
25
|
+
avg: trend.values.avg,
|
|
26
|
+
min: trend.values.min,
|
|
27
|
+
med: trend.values.med,
|
|
28
|
+
max: trend.values.max,
|
|
29
|
+
'p(95)': trend.values['p(95)'],
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function buildAppMetricsReport(metricsData) {
|
|
33
|
+
const heapSizeTotal = prometheus_metrics_parser_1.PrometheusMetricsParser.calculateMetricStats(metricsData, 'n8n_nodejs_heap_size_total_bytes');
|
|
34
|
+
const heapSizeUsed = prometheus_metrics_parser_1.PrometheusMetricsParser.calculateMetricStats(metricsData, 'n8n_nodejs_heap_size_used_bytes');
|
|
35
|
+
const externalMemory = prometheus_metrics_parser_1.PrometheusMetricsParser.calculateMetricStats(metricsData, 'n8n_nodejs_external_memory_bytes');
|
|
36
|
+
const eventLoopLag = prometheus_metrics_parser_1.PrometheusMetricsParser.calculateMetricStats(metricsData, 'n8n_nodejs_eventloop_lag_seconds');
|
|
37
|
+
return {
|
|
38
|
+
...(heapSizeTotal && { heapSizeTotal }),
|
|
39
|
+
...(heapSizeUsed && { heapSizeUsed }),
|
|
40
|
+
...(externalMemory && { externalMemory }),
|
|
41
|
+
...(eventLoopLag && { eventLoopLag }),
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
function buildTestReport(scenario, endOfTestSummary, tags, appMetricsData) {
|
|
45
|
+
const appMetrics = appMetricsData ? buildAppMetricsReport(appMetricsData) : undefined;
|
|
46
|
+
return {
|
|
47
|
+
runId: (0, nanoid_1.nanoid)(),
|
|
48
|
+
ts: new Date().toISOString(),
|
|
49
|
+
scenarioName: scenario.name,
|
|
50
|
+
tags,
|
|
51
|
+
checks: endOfTestSummary.root_group.checks.map(k6CheckToCheck),
|
|
52
|
+
metrics: {
|
|
53
|
+
dataReceived: k6CounterToCounter(endOfTestSummary.metrics.data_received),
|
|
54
|
+
dataSent: k6CounterToCounter(endOfTestSummary.metrics.data_sent),
|
|
55
|
+
httpRequests: k6CounterToCounter(endOfTestSummary.metrics.http_reqs),
|
|
56
|
+
httpRequestDuration: k6TrendToTrend(endOfTestSummary.metrics.http_req_duration),
|
|
57
|
+
httpRequestSending: k6TrendToTrend(endOfTestSummary.metrics.http_req_sending),
|
|
58
|
+
httpRequestReceiving: k6TrendToTrend(endOfTestSummary.metrics.http_req_receiving),
|
|
59
|
+
httpRequestWaiting: k6TrendToTrend(endOfTestSummary.metrics.http_req_waiting),
|
|
60
|
+
iterations: k6CounterToCounter(endOfTestSummary.metrics.iterations),
|
|
61
|
+
},
|
|
62
|
+
...(appMetrics && { appMetrics }),
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=test-report.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-report.js","sourceRoot":"","sources":["../../src/test-execution/test-report.ts"],"names":[],"mappings":";;AAgGA,sDAwBC;AAKD,0CA0BC;AAvJD,mCAAgC;AAEhC,0FAAqF;AA+DrF,SAAS,cAAc,CAAC,KAAc;IACrC,OAAO;QACN,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,KAAK,EAAE,KAAK,CAAC,KAAK;KAClB,CAAC;AACH,CAAC;AAED,SAAS,kBAAkB,CAAC,OAAwB;IACnD,OAAO;QACN,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,KAAK;QAC3B,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI;KACzB,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,KAAoB;IAC3C,OAAO;QACN,IAAI,EAAE,OAAO;QACb,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC;QAC9B,GAAG,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG;QACrB,GAAG,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG;QACrB,GAAG,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG;QACrB,GAAG,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG;QACrB,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC;KAC9B,CAAC;AACH,CAAC;AAKD,SAAgB,qBAAqB,CAAC,WAAqB;IAC1D,MAAM,aAAa,GAAG,mDAAuB,CAAC,oBAAoB,CACjE,WAAW,EACX,kCAAkC,CAClC,CAAC;IACF,MAAM,YAAY,GAAG,mDAAuB,CAAC,oBAAoB,CAChE,WAAW,EACX,iCAAiC,CACjC,CAAC;IACF,MAAM,cAAc,GAAG,mDAAuB,CAAC,oBAAoB,CAClE,WAAW,EACX,kCAAkC,CAClC,CAAC;IACF,MAAM,YAAY,GAAG,mDAAuB,CAAC,oBAAoB,CAChE,WAAW,EACX,kCAAkC,CAClC,CAAC;IAEF,OAAO;QACN,GAAG,CAAC,aAAa,IAAI,EAAE,aAAa,EAAE,CAAC;QACvC,GAAG,CAAC,YAAY,IAAI,EAAE,YAAY,EAAE,CAAC;QACrC,GAAG,CAAC,cAAc,IAAI,EAAE,cAAc,EAAE,CAAC;QACzC,GAAG,CAAC,YAAY,IAAI,EAAE,YAAY,EAAE,CAAC;KACrC,CAAC;AACH,CAAC;AAKD,SAAgB,eAAe,CAC9B,QAAkB,EAClB,gBAAoC,EACpC,IAAa,EACb,cAAyB;IAEzB,MAAM,UAAU,GAAG,cAAc,CAAC,CAAC,CAAC,qBAAqB,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAEtF,OAAO;QACN,KAAK,EAAE,IAAA,eAAM,GAAE;QACf,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QAC5B,YAAY,EAAE,QAAQ,CAAC,IAAI;QAC3B,IAAI;QACJ,MAAM,EAAE,gBAAgB,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC;QAC9D,OAAO,EAAE;YACR,YAAY,EAAE,kBAAkB,CAAC,gBAAgB,CAAC,OAAO,CAAC,aAAa,CAAC;YACxE,QAAQ,EAAE,kBAAkB,CAAC,gBAAgB,CAAC,OAAO,CAAC,SAAS,CAAC;YAChE,YAAY,EAAE,kBAAkB,CAAC,gBAAgB,CAAC,OAAO,CAAC,SAAS,CAAC;YACpE,mBAAmB,EAAE,cAAc,CAAC,gBAAgB,CAAC,OAAO,CAAC,iBAAiB,CAAC;YAC/E,kBAAkB,EAAE,cAAc,CAAC,gBAAgB,CAAC,OAAO,CAAC,gBAAgB,CAAC;YAC7E,oBAAoB,EAAE,cAAc,CAAC,gBAAgB,CAAC,OAAO,CAAC,kBAAkB,CAAC;YACjF,kBAAkB,EAAE,cAAc,CAAC,gBAAgB,CAAC,OAAO,CAAC,gBAAgB,CAAC;YAC7E,UAAU,EAAE,kBAAkB,CAAC,gBAAgB,CAAC,OAAO,CAAC,UAAU,CAAC;SACnE;QACD,GAAG,CAAC,UAAU,IAAI,EAAE,UAAU,EAAE,CAAC;KACjC,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type ScenarioData = {
|
|
2
|
+
workflowFiles?: string[];
|
|
3
|
+
credentialFiles?: string[];
|
|
4
|
+
dataTableFile?: string;
|
|
5
|
+
};
|
|
6
|
+
export type ScenarioManifest = {
|
|
7
|
+
name: string;
|
|
8
|
+
description: string;
|
|
9
|
+
scriptPath: string;
|
|
10
|
+
scenarioData: ScenarioData;
|
|
11
|
+
};
|
|
12
|
+
export type Scenario = ScenarioManifest & {
|
|
13
|
+
id: string;
|
|
14
|
+
scenarioDirPath: string;
|
|
15
|
+
dataTableId?: string;
|
|
16
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scenario.js","sourceRoot":"","sources":["../../src/types/scenario.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { defineConfig, globalIgnores } from 'eslint/config';
|
|
2
|
+
import { nodeConfig } from '@n8n/eslint-config/node';
|
|
3
|
+
|
|
4
|
+
export default defineConfig(
|
|
5
|
+
nodeConfig,
|
|
6
|
+
globalIgnores(['scenarios/**', 'scripts/**']),
|
|
7
|
+
{
|
|
8
|
+
rules: {
|
|
9
|
+
'unicorn/filename-case': ['error', { case: 'kebabCase' }],
|
|
10
|
+
'n8n-local-rules/no-plain-errors': 'off',
|
|
11
|
+
complexity: 'error',
|
|
12
|
+
'@typescript-eslint/naming-convention': 'warn',
|
|
13
|
+
'no-empty': 'warn',
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
files: ['./src/commands/*.ts'],
|
|
18
|
+
rules: {
|
|
19
|
+
'import-x/no-default-export': 'off',
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
);
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# This file is maintained automatically by "terraform init".
|
|
2
|
+
# Manual edits may be lost in future updates.
|
|
3
|
+
|
|
4
|
+
provider "registry.terraform.io/hashicorp/azurerm" {
|
|
5
|
+
version = "3.115.0"
|
|
6
|
+
constraints = "~> 3.115.0"
|
|
7
|
+
hashes = [
|
|
8
|
+
"h1:O7C3Xb+MSOc9C/eAJ5C/CiJ4vuvUsYxxIzr9ZurmHNI=",
|
|
9
|
+
"zh:0ea93abd53cb872691bad6d5625bda88b5d9619ea813c208b36e0ee236308589",
|
|
10
|
+
"zh:26703cb9c2c38bc43e97bc83af03559d065750856ea85834b71fbcb2ef9d935c",
|
|
11
|
+
"zh:316255a3391c49fe9bd7c5b6aa53b56dd490e1083d19b722e7b8f956a2dfe004",
|
|
12
|
+
"zh:431637ae90c592126fb1ec813fee6390604275438a0d5e15904c65b0a6a0f826",
|
|
13
|
+
"zh:4cee0fa2e84f89853723c0bc72b7debf8ea2ffffc7ae34ff28d8a69269d3a879",
|
|
14
|
+
"zh:64a3a3c78ea877515365ed336bd0f3abbe71db7c99b3d2837915fbca168d429c",
|
|
15
|
+
"zh:7380d7b503b5a87fd71a31360c3eeab504f78e4f314824e3ceda724d9dc74cf0",
|
|
16
|
+
"zh:974213e05708037a6d2d8c58cc84981819138f44fe40e344034eb80e16ca6012",
|
|
17
|
+
"zh:9a91614de0476074e9c62bbf08d3bb9c64adbd1d3a4a2b5a3e8e41d9d6d5672f",
|
|
18
|
+
"zh:a438471c85b8788ab21bdef4cd5ca391a46cbae33bd0262668a80f5e6c4610e1",
|
|
19
|
+
"zh:bf823f2c941b336a1208f015466212b1a8fdf6da28abacf59bea708377709d9e",
|
|
20
|
+
"zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c",
|
|
21
|
+
]
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
provider "registry.terraform.io/hashicorp/random" {
|
|
25
|
+
version = "3.6.2"
|
|
26
|
+
hashes = [
|
|
27
|
+
"h1:VavG5unYCa3SYISMKF9pzc3718M0bhPlcbUZZGl7wuo=",
|
|
28
|
+
"zh:0ef01a4f81147b32c1bea3429974d4d104bbc4be2ba3cfa667031a8183ef88ec",
|
|
29
|
+
"zh:1bcd2d8161e89e39886119965ef0f37fcce2da9c1aca34263dd3002ba05fcb53",
|
|
30
|
+
"zh:37c75d15e9514556a5f4ed02e1548aaa95c0ecd6ff9af1119ac905144c70c114",
|
|
31
|
+
"zh:4210550a767226976bc7e57d988b9ce48f4411fa8a60cd74a6b246baf7589dad",
|
|
32
|
+
"zh:562007382520cd4baa7320f35e1370ffe84e46ed4e2071fdc7e4b1a9b1f8ae9b",
|
|
33
|
+
"zh:5efb9da90f665e43f22c2e13e0ce48e86cae2d960aaf1abf721b497f32025916",
|
|
34
|
+
"zh:6f71257a6b1218d02a573fc9bff0657410404fb2ef23bc66ae8cd968f98d5ff6",
|
|
35
|
+
"zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
|
|
36
|
+
"zh:9647e18f221380a85f2f0ab387c68fdafd58af6193a932417299cdcae4710150",
|
|
37
|
+
"zh:bb6297ce412c3c2fa9fec726114e5e0508dd2638cad6a0cb433194930c97a544",
|
|
38
|
+
"zh:f83e925ed73ff8a5ef6e3608ad9225baa5376446349572c2449c0c0b3cf184b7",
|
|
39
|
+
"zh:fbef0781cb64de76b1df1ca11078aecba7800d82fd4a956302734999cfd9a4af",
|
|
40
|
+
]
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
provider "registry.terraform.io/hashicorp/tls" {
|
|
44
|
+
version = "4.0.5"
|
|
45
|
+
hashes = [
|
|
46
|
+
"h1:zeG5RmggBZW/8JWIVrdaeSJa0OG62uFX5HY1eE8SjzY=",
|
|
47
|
+
"zh:01cfb11cb74654c003f6d4e32bbef8f5969ee2856394a96d127da4949c65153e",
|
|
48
|
+
"zh:0472ea1574026aa1e8ca82bb6df2c40cd0478e9336b7a8a64e652119a2fa4f32",
|
|
49
|
+
"zh:1a8ddba2b1550c5d02003ea5d6cdda2eef6870ece86c5619f33edd699c9dc14b",
|
|
50
|
+
"zh:1e3bb505c000adb12cdf60af5b08f0ed68bc3955b0d4d4a126db5ca4d429eb4a",
|
|
51
|
+
"zh:6636401b2463c25e03e68a6b786acf91a311c78444b1dc4f97c539f9f78de22a",
|
|
52
|
+
"zh:76858f9d8b460e7b2a338c477671d07286b0d287fd2d2e3214030ae8f61dd56e",
|
|
53
|
+
"zh:a13b69fb43cb8746793b3069c4d897bb18f454290b496f19d03c3387d1c9a2dc",
|
|
54
|
+
"zh:a90ca81bb9bb509063b736842250ecff0f886a91baae8de65c8430168001dad9",
|
|
55
|
+
"zh:c4de401395936e41234f1956ebadbd2ed9f414e6908f27d578614aaa529870d4",
|
|
56
|
+
"zh:c657e121af8fde19964482997f0de2d5173217274f6997e16389e7707ed8ece8",
|
|
57
|
+
"zh:d68b07a67fbd604c38ec9733069fbf23441436fecf554de6c75c032f82e1ef19",
|
|
58
|
+
"zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c",
|
|
59
|
+
]
|
|
60
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
|
|
2
|
+
data "azurerm_resource_group" "main" {
|
|
3
|
+
name = var.resource_group_name
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
# Random prefix for the resources
|
|
7
|
+
resource "random_string" "prefix" {
|
|
8
|
+
length = 8
|
|
9
|
+
special = false
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
# SSH key pair
|
|
13
|
+
resource "tls_private_key" "ssh_key" {
|
|
14
|
+
algorithm = "RSA"
|
|
15
|
+
rsa_bits = 4096
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
# Dedicated Host Group & Hosts
|
|
19
|
+
|
|
20
|
+
resource "azurerm_dedicated_host_group" "main" {
|
|
21
|
+
name = "${random_string.prefix.result}-hostgroup"
|
|
22
|
+
location = var.location
|
|
23
|
+
resource_group_name = data.azurerm_resource_group.main.name
|
|
24
|
+
platform_fault_domain_count = 1
|
|
25
|
+
automatic_placement_enabled = false
|
|
26
|
+
zone = 1
|
|
27
|
+
|
|
28
|
+
tags = local.common_tags
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
resource "azurerm_dedicated_host" "hosts" {
|
|
32
|
+
name = "${random_string.prefix.result}-host"
|
|
33
|
+
location = var.location
|
|
34
|
+
dedicated_host_group_id = azurerm_dedicated_host_group.main.id
|
|
35
|
+
sku_name = var.host_size_family
|
|
36
|
+
platform_fault_domain = 0
|
|
37
|
+
|
|
38
|
+
tags = local.common_tags
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
# VM
|
|
42
|
+
|
|
43
|
+
module "test_vm" {
|
|
44
|
+
source = "./modules/benchmark-vm"
|
|
45
|
+
|
|
46
|
+
location = var.location
|
|
47
|
+
resource_group_name = data.azurerm_resource_group.main.name
|
|
48
|
+
prefix = random_string.prefix.result
|
|
49
|
+
dedicated_host_id = azurerm_dedicated_host.hosts.id
|
|
50
|
+
ssh_public_key = tls_private_key.ssh_key.public_key_openssh
|
|
51
|
+
vm_size = var.vm_size
|
|
52
|
+
|
|
53
|
+
tags = local.common_tags
|
|
54
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
variable "location" {
|
|
2
|
+
description = "Region to deploy resources"
|
|
3
|
+
default = "East US"
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
variable "resource_group_name" {
|
|
7
|
+
description = "Name of the resource group"
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
variable "prefix" {
|
|
11
|
+
description = "Prefix to append to resources"
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
variable "dedicated_host_id" {
|
|
15
|
+
description = "Dedicated Host ID"
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
variable "ssh_public_key" {
|
|
19
|
+
description = "SSH Public Key"
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
variable "vm_size" {
|
|
23
|
+
description = "VM Size"
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
variable "tags" {
|
|
27
|
+
description = "Tags to apply to all resources created by this module"
|
|
28
|
+
type = map(string)
|
|
29
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# Network
|
|
2
|
+
|
|
3
|
+
resource "azurerm_virtual_network" "main" {
|
|
4
|
+
name = "${var.prefix}-vnet"
|
|
5
|
+
location = var.location
|
|
6
|
+
resource_group_name = var.resource_group_name
|
|
7
|
+
address_space = ["10.0.0.0/16"]
|
|
8
|
+
|
|
9
|
+
tags = var.tags
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
resource "azurerm_subnet" "main" {
|
|
13
|
+
name = "${var.prefix}-subnet"
|
|
14
|
+
resource_group_name = var.resource_group_name
|
|
15
|
+
virtual_network_name = azurerm_virtual_network.main.name
|
|
16
|
+
address_prefixes = ["10.0.0.0/24"]
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
resource "azurerm_network_security_group" "ssh" {
|
|
20
|
+
name = "${var.prefix}-nsg"
|
|
21
|
+
location = var.location
|
|
22
|
+
resource_group_name = var.resource_group_name
|
|
23
|
+
|
|
24
|
+
security_rule {
|
|
25
|
+
name = "AllowSSH"
|
|
26
|
+
priority = 1001
|
|
27
|
+
direction = "Inbound"
|
|
28
|
+
access = "Allow"
|
|
29
|
+
protocol = "Tcp"
|
|
30
|
+
source_port_range = "*"
|
|
31
|
+
destination_port_range = "22"
|
|
32
|
+
source_address_prefix = "*"
|
|
33
|
+
destination_address_prefix = "*"
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
tags = var.tags
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
resource "azurerm_public_ip" "main" {
|
|
40
|
+
name = "${var.prefix}-pip"
|
|
41
|
+
location = var.location
|
|
42
|
+
resource_group_name = var.resource_group_name
|
|
43
|
+
allocation_method = "Static"
|
|
44
|
+
sku = "Standard"
|
|
45
|
+
|
|
46
|
+
tags = var.tags
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
resource "azurerm_network_interface" "main" {
|
|
50
|
+
name = "${var.prefix}-nic"
|
|
51
|
+
location = var.location
|
|
52
|
+
resource_group_name = var.resource_group_name
|
|
53
|
+
|
|
54
|
+
ip_configuration {
|
|
55
|
+
name = "${var.prefix}-ipconfig"
|
|
56
|
+
subnet_id = azurerm_subnet.main.id
|
|
57
|
+
private_ip_address_allocation = "Dynamic"
|
|
58
|
+
public_ip_address_id = azurerm_public_ip.main.id
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
tags = var.tags
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
resource "azurerm_network_interface_security_group_association" "ssh" {
|
|
65
|
+
network_interface_id = azurerm_network_interface.main.id
|
|
66
|
+
network_security_group_id = azurerm_network_security_group.ssh.id
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
# Disk
|
|
70
|
+
|
|
71
|
+
resource "azurerm_managed_disk" "data" {
|
|
72
|
+
name = "${var.prefix}-disk"
|
|
73
|
+
location = var.location
|
|
74
|
+
resource_group_name = var.resource_group_name
|
|
75
|
+
storage_account_type = "PremiumV2_LRS"
|
|
76
|
+
create_option = "Empty"
|
|
77
|
+
disk_size_gb = "32"
|
|
78
|
+
zone = 1
|
|
79
|
+
|
|
80
|
+
tags = var.tags
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
resource "azurerm_virtual_machine_data_disk_attachment" "data" {
|
|
84
|
+
managed_disk_id = azurerm_managed_disk.data.id
|
|
85
|
+
virtual_machine_id = azurerm_linux_virtual_machine.main.id
|
|
86
|
+
lun = "1"
|
|
87
|
+
caching = "None"
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
# VM
|
|
91
|
+
|
|
92
|
+
resource "azurerm_linux_virtual_machine" "main" {
|
|
93
|
+
name = "${var.prefix}-vm"
|
|
94
|
+
location = var.location
|
|
95
|
+
resource_group_name = var.resource_group_name
|
|
96
|
+
network_interface_ids = [azurerm_network_interface.main.id]
|
|
97
|
+
dedicated_host_id = var.dedicated_host_id
|
|
98
|
+
zone = 1
|
|
99
|
+
|
|
100
|
+
size = var.vm_size
|
|
101
|
+
|
|
102
|
+
admin_username = "benchmark"
|
|
103
|
+
|
|
104
|
+
admin_ssh_key {
|
|
105
|
+
username = "benchmark"
|
|
106
|
+
public_key = var.ssh_public_key
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
os_disk {
|
|
110
|
+
caching = "ReadWrite"
|
|
111
|
+
storage_account_type = "Premium_LRS"
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
source_image_reference {
|
|
115
|
+
publisher = "Canonical"
|
|
116
|
+
offer = "0001-com-ubuntu-server-jammy"
|
|
117
|
+
sku = "22_04-lts-gen2"
|
|
118
|
+
version = "latest"
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
identity {
|
|
122
|
+
type = "SystemAssigned"
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
tags = var.tags
|
|
126
|
+
}
|
package/infra/output.tf
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
output "vm_name" {
|
|
2
|
+
value = module.test_vm.vm_name
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
output "ip" {
|
|
6
|
+
value = module.test_vm.ip
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
output "ssh_username" {
|
|
10
|
+
value = module.test_vm.ssh_username
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
output "ssh_private_key" {
|
|
14
|
+
value = tls_private_key.ssh_key.private_key_pem
|
|
15
|
+
sensitive = true
|
|
16
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
|
|
2
|
+
terraform {
|
|
3
|
+
required_providers {
|
|
4
|
+
azurerm = {
|
|
5
|
+
source = "hashicorp/azurerm"
|
|
6
|
+
version = "~> 3.115.0"
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
random = {
|
|
10
|
+
source = "hashicorp/random"
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
required_version = "~> 1.8.5"
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
provider "azurerm" {
|
|
18
|
+
features {}
|
|
19
|
+
|
|
20
|
+
skip_provider_registration = true
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
provider "random" {}
|
package/infra/vars.tf
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
variable "location" {
|
|
2
|
+
description = "Region to deploy resources"
|
|
3
|
+
default = "East US"
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
variable "resource_group_name" {
|
|
7
|
+
description = "Name of the resource group"
|
|
8
|
+
default = "n8n-benchmarking"
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
variable "host_size_family" {
|
|
12
|
+
description = "Size Family for the Host Group"
|
|
13
|
+
default = "DCSv2-Type1"
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
variable "vm_size" {
|
|
17
|
+
description = "VM Size"
|
|
18
|
+
# 8 vCPUs, 32 GiB memory
|
|
19
|
+
default = "Standard_DC8_v2"
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
variable "number_of_vms" {
|
|
23
|
+
description = "Number of VMs to create"
|
|
24
|
+
default = 1
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
locals {
|
|
28
|
+
common_tags = {
|
|
29
|
+
Id = "N8nBenchmark"
|
|
30
|
+
Terraform = "true"
|
|
31
|
+
Owner = "Catalysts"
|
|
32
|
+
CreatedAt = timestamp()
|
|
33
|
+
}
|
|
34
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@atom8n/n8n-benchmark",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "Cli for running benchmark tests for n8n",
|
|
5
|
+
"main": "dist/index",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"build": "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json",
|
|
8
|
+
"format": "biome format --write .",
|
|
9
|
+
"format:check": "biome ci .",
|
|
10
|
+
"lint": "eslint . --quiet",
|
|
11
|
+
"lint:fix": "eslint . --fix",
|
|
12
|
+
"start": "./bin/n8n-benchmark",
|
|
13
|
+
"test": "echo \"WARNING: no test specified\" && exit 0",
|
|
14
|
+
"typecheck": "tsc --noEmit",
|
|
15
|
+
"benchmark": "zx scripts/run.mjs",
|
|
16
|
+
"benchmark-in-cloud": "pnpm benchmark --env cloud",
|
|
17
|
+
"benchmark-locally": "pnpm benchmark --env local",
|
|
18
|
+
"provision-cloud-env": "zx scripts/provision-cloud-env.mjs",
|
|
19
|
+
"destroy-cloud-env": "zx scripts/destroy-cloud-env.mjs",
|
|
20
|
+
"watch": "tsc-watch -p tsconfig.build.json --onCompilationComplete \"tsc-alias -p tsconfig.build.json\""
|
|
21
|
+
},
|
|
22
|
+
"engines": {
|
|
23
|
+
"node": ">=22.16"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"automate",
|
|
27
|
+
"automation",
|
|
28
|
+
"IaaS",
|
|
29
|
+
"iPaaS",
|
|
30
|
+
"n8n",
|
|
31
|
+
"workflow",
|
|
32
|
+
"benchmark",
|
|
33
|
+
"performance"
|
|
34
|
+
],
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@oclif/core": "4.0.7",
|
|
37
|
+
"axios": "catalog:",
|
|
38
|
+
"dotenv": "17.2.3",
|
|
39
|
+
"nanoid": "catalog:",
|
|
40
|
+
"zx": "^8.1.4"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@atom8n/typescript-config": "1.3.0",
|
|
44
|
+
"@types/convict": "^6.1.1",
|
|
45
|
+
"@types/k6": "^0.52.0"
|
|
46
|
+
},
|
|
47
|
+
"bin": {
|
|
48
|
+
"n8n-benchmark": "./bin/n8n-benchmark"
|
|
49
|
+
},
|
|
50
|
+
"oclif": {
|
|
51
|
+
"bin": "n8n-benchmark",
|
|
52
|
+
"commands": "./dist/commands",
|
|
53
|
+
"topicSeparator": " "
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"createdAt": "2024-09-03T11:51:56.540Z",
|
|
3
|
+
"updatedAt": "2024-09-03T12:22:21.000Z",
|
|
4
|
+
"name": "Binary Data",
|
|
5
|
+
"active": true,
|
|
6
|
+
"nodes": [
|
|
7
|
+
{
|
|
8
|
+
"parameters": {
|
|
9
|
+
"httpMethod": "POST",
|
|
10
|
+
"path": "binary-files-benchmark",
|
|
11
|
+
"responseMode": "responseNode",
|
|
12
|
+
"options": {}
|
|
13
|
+
},
|
|
14
|
+
"type": "n8n-nodes-base.webhook",
|
|
15
|
+
"typeVersion": 2,
|
|
16
|
+
"position": [0, 0],
|
|
17
|
+
"id": "bfe19f12-3655-440f-be5c-8d71665c6353",
|
|
18
|
+
"name": "Webhook",
|
|
19
|
+
"webhookId": "109d7b13-93ad-42b0-a9ce-ca49e1817b35"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"parameters": { "respondWith": "binary", "options": {} },
|
|
23
|
+
"type": "n8n-nodes-base.respondToWebhook",
|
|
24
|
+
"typeVersion": 1.1,
|
|
25
|
+
"position": [740, 0],
|
|
26
|
+
"id": "cd957c9b-6b7a-4423-aac3-6df4d8bb571e",
|
|
27
|
+
"name": "Respond to Webhook"
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"parameters": {
|
|
31
|
+
"operation": "write",
|
|
32
|
+
"fileName": "=file-{{ Date.now() }}-{{ Math.random() }}.js",
|
|
33
|
+
"dataPropertyName": "file",
|
|
34
|
+
"options": {}
|
|
35
|
+
},
|
|
36
|
+
"type": "n8n-nodes-base.readWriteFile",
|
|
37
|
+
"typeVersion": 1,
|
|
38
|
+
"position": [260, 0],
|
|
39
|
+
"id": "f2ce4709-7697-4bc6-8eca-6c222485297a",
|
|
40
|
+
"name": "Write File to Disk"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"parameters": { "fileSelector": "={{ $json.fileName }}", "options": {} },
|
|
44
|
+
"type": "n8n-nodes-base.readWriteFile",
|
|
45
|
+
"typeVersion": 1,
|
|
46
|
+
"position": [500, 0],
|
|
47
|
+
"id": "198e8a6c-81a3-4b34-b099-501961a02006",
|
|
48
|
+
"name": "Read File from Disk"
|
|
49
|
+
}
|
|
50
|
+
],
|
|
51
|
+
"connections": {
|
|
52
|
+
"Webhook": { "main": [[{ "node": "Write File to Disk", "type": "main", "index": 0 }]] },
|
|
53
|
+
"Write File to Disk": {
|
|
54
|
+
"main": [[{ "node": "Read File from Disk", "type": "main", "index": 0 }]]
|
|
55
|
+
},
|
|
56
|
+
"Read File from Disk": {
|
|
57
|
+
"main": [[{ "node": "Respond to Webhook", "type": "main", "index": 0 }]]
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
"settings": { "executionOrder": "v1" },
|
|
61
|
+
"staticData": null,
|
|
62
|
+
"meta": null,
|
|
63
|
+
"pinData": {},
|
|
64
|
+
"versionId": "8dd197c0-d1ea-43c3-9f88-9d11e7b081a0",
|
|
65
|
+
"triggerCount": 1,
|
|
66
|
+
"tags": []
|
|
67
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "../scenario.schema.json",
|
|
3
|
+
"name": "BinaryData",
|
|
4
|
+
"description": "Send a binary file to a webhook, write it to FS, read it from FS and receive it back",
|
|
5
|
+
"scenarioData": { "workflowFiles": ["binary-data.json"] },
|
|
6
|
+
"scriptPath": "binary-data.script.js"
|
|
7
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import http from 'k6/http';
|
|
2
|
+
import { check } from 'k6';
|
|
3
|
+
|
|
4
|
+
const apiBaseUrl = __ENV.API_BASE_URL;
|
|
5
|
+
|
|
6
|
+
// This creates a 2MB file (16 * 128 * 1024 = 2 * 1024 * 1024 = 2MB)
|
|
7
|
+
const file = Array.from({ length: 128 * 1024 }, () => Math.random().toString().slice(2)).join('');
|
|
8
|
+
const filename = 'test.bin';
|
|
9
|
+
|
|
10
|
+
export default function () {
|
|
11
|
+
const data = {
|
|
12
|
+
filename,
|
|
13
|
+
file: http.file(file, filename, 'application/javascript'),
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const res = http.post(`${apiBaseUrl}/webhook/binary-files-benchmark`, data);
|
|
17
|
+
|
|
18
|
+
if (res.status !== 200) {
|
|
19
|
+
console.error(
|
|
20
|
+
`Invalid response. Received status ${res.status}. Body: ${JSON.stringify(res.body)}`,
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
check(res, {
|
|
25
|
+
'is status 200': (r) => r.status === 200,
|
|
26
|
+
'has correct content type': (r) =>
|
|
27
|
+
r.headers['Content-Type'] === 'application/javascript; charset=utf-8',
|
|
28
|
+
});
|
|
29
|
+
}
|