Skip to content

Commit d05a757

Browse files
try with connect: { timeout: 60000 }
1 parent bb22271 commit d05a757

2 files changed

Lines changed: 109 additions & 1 deletion

File tree

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import { describe, test, expect, jest } from "@jest/globals";
2+
import { orkesConductorClient } from "../../src/orkes";
3+
import { WorkflowExecutor } from "../../src/core";
4+
import { TaskType } from "../../src/common";
5+
6+
// --- Configuration for the Load Test ---
7+
// The number of requests to send in parallel.
8+
// Adjust this number to find the breaking point of your load balancer.
9+
const CONCURRENT_REQUESTS = 5000;
10+
const TEST_TIMEOUT = 60000; // 60 seconds
11+
12+
describe("Load Test for ECONNRESET", () => {
13+
jest.setTimeout(TEST_TIMEOUT);
14+
15+
test(`should handle ${CONCURRENT_REQUESTS} concurrent GET requests without ECONNRESET`, async () => {
16+
const client = await orkesConductorClient();
17+
const executor = new WorkflowExecutor(client);
18+
19+
// To ensure we are making valid API calls, we first create a simple
20+
// workflow and start one execution. We will then query this execution's status.
21+
const workflowName = "load_test_workflow";
22+
await executor.registerWorkflow(true, {
23+
name: workflowName,
24+
version: 1,
25+
tasks: [
26+
{
27+
name: "simple_task",
28+
taskReferenceName: "simple_task_ref",
29+
type: TaskType.SIMPLE,
30+
},
31+
],
32+
timeoutSeconds: 0,
33+
inputParameters: [],
34+
});
35+
const executionId = await executor.startWorkflow({
36+
name: workflowName,
37+
version: 1,
38+
});
39+
40+
console.log(
41+
`Starting load test with workflow execution ID: ${executionId}`
42+
);
43+
console.log(`Sending ${CONCURRENT_REQUESTS} concurrent requests...`);
44+
45+
// Create an array of promises. Each promise represents a GET request.
46+
const requestPromises = [];
47+
for (let i = 0; i < CONCURRENT_REQUESTS; i++) {
48+
requestPromises.push(executor.getWorkflow(executionId, false));
49+
}
50+
51+
// Use Promise.allSettled to wait for all requests to complete,
52+
// regardless of whether they succeed or fail.
53+
const results = await Promise.allSettled(requestPromises);
54+
55+
// Analyze the results to find ECONNRESET errors
56+
let successCount = 0;
57+
const econnresetErrors: any[] = [];
58+
const http429Errors: any[] = [];
59+
const otherErrors: any[] = [];
60+
61+
results.forEach((result, index) => {
62+
if (result.status === "fulfilled") {
63+
successCount++;
64+
} else {
65+
const reason = result.reason;
66+
// Check if the rejection reason is the specific ECONNRESET error
67+
if (reason?.code === "ECONNRESET") {
68+
econnresetErrors.push({ requestIndex: index, reason });
69+
} else if (reason?.body?.status === 429) {
70+
http429Errors.push({ requestIndex: index, reason });
71+
} else {
72+
otherErrors.push({ requestIndex: index, reason });
73+
}
74+
}
75+
});
76+
77+
console.log("--- Load Test Results ---");
78+
console.log(
79+
`Successful Requests: ${successCount} / ${CONCURRENT_REQUESTS}`
80+
);
81+
console.log(`ECONNRESET Failures: ${econnresetErrors.length}`);
82+
console.log(`HTTP 429 Failures: ${http429Errors.length}`);
83+
console.log(`Other Failures: ${otherErrors.length}`);
84+
console.log("-------------------------");
85+
86+
if (econnresetErrors.length > 0) {
87+
console.error("ECONNRESET errors detected:", econnresetErrors);
88+
}
89+
if (http429Errors.length > 0) {
90+
console.error("HTTP 429 (Too Many Requests) errors detected:", http429Errors);
91+
}
92+
if (otherErrors.length > 0) {
93+
console.error(`\n--- Other Errors (${otherErrors.length}) ---`);
94+
for (const error of otherErrors) {
95+
console.error(
96+
`Request Index ${error.requestIndex} failed. Reason:`,
97+
error.reason
98+
);
99+
}
100+
console.error("--------------------------\n");
101+
}
102+
103+
// The test assertion: Fail if we encounter any ECONNRESET errors.
104+
expect(econnresetErrors.length).toBe(0);
105+
expect(http429Errors.length).toBe(0);
106+
expect(otherErrors.length).toBe(0);
107+
});
108+
});

src/orkes/helpers/resolveFetchFn.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export const resolveFetchFn = async (
1616
//const undiciAgent = new Agent({ allowH2: true, keepAliveTimeout: 1});
1717

1818
return ((input: RequestInfo, init?: RequestInit) =>
19-
undiciFetch(input, { ...init, dispatcher: new Agent({ allowH2: true }) })) as FetchFn;
19+
undiciFetch(input, { ...init, dispatcher: new Agent({ allowH2: true, connect: { timeout: 60000 } }) })) as FetchFn;
2020
} catch {
2121
return fetch;
2222
}

0 commit comments

Comments
 (0)