Skip to content

Commit e759739

Browse files
authored
fix(keepalive): cache http agent by host, set keepalive for first request (#65)
1 parent 3733bf2 commit e759739

File tree

4 files changed

+43
-59
lines changed

4 files changed

+43
-59
lines changed

package-lock.json

Lines changed: 0 additions & 41 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
"eslint-plugin-prettier": "^4.0.0",
3333
"jest": "^27.5.1",
3434
"msw": "^0.45.0",
35-
"nock": "^13.3.6",
3635
"prettier": "^2.4.1",
3736
"standard-version": "^9.3.2",
3837
"ts-jest": "^27.0.7",

src/http/node.ts

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,44 @@ const DEFAULT_ERROR = "Server error";
2525

2626
const DEFAULT_USER_AGENT = systemInfoString();
2727

28+
const createSocket = HttpsAgent.prototype.createSocket;
29+
30+
const agentOptions = {
31+
keepAlive: true,
32+
keepAliveMsecs: 1000,
33+
timeout: 0,
34+
freeSocketTimeout: 30000
35+
};
36+
37+
// workaround to set keep alive timeout on first request
38+
// Keep Alive option is not working on https.agent #47137
39+
// https://github.com/nodejs/node/issues/47137
40+
41+
HttpsAgent.prototype.createSocket = function (req, options, cb) {
42+
req.on("socket", socket => {
43+
socket.setKeepAlive(agentOptions.keepAlive, agentOptions.keepAliveMsecs);
44+
});
45+
createSocket.call(this, req, options, cb);
46+
};
47+
2848
export class NodeHttpClient {
2949
authenticator!: Authenticator;
50+
agentCache!: Map<string, HttpsAgent>;
51+
52+
constructor() {
53+
this.agentCache = new Map();
54+
}
55+
56+
getAgent = (url: string): HttpsAgent => {
57+
const { hostname } = new URL(`https://${url}`);
58+
if (this.agentCache.has(hostname)) {
59+
return this.agentCache.get(hostname) as HttpsAgent;
60+
}
61+
62+
const agent = new HttpsAgent(agentOptions);
63+
this.agentCache.set(hostname, agent);
64+
return agent;
65+
};
3066

3167
request<T>(
3268
method: string,
@@ -38,12 +74,7 @@ export class NodeHttpClient {
3874
} {
3975
const { headers = {}, body, retry = true } = options || {};
4076
const controller = new AbortController();
41-
const agent = new HttpsAgent({
42-
keepAlive: true,
43-
keepAliveMsecs: 1000,
44-
timeout: 60000,
45-
freeSocketTimeout: 30000
46-
});
77+
const agent = this.getAgent(url);
4778

4879
const abort = () => {
4980
controller.abort();

test/integration/long.test.ts

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { Firebolt } from "../../src/index";
2-
import nock from "nock";
32

43
const connectionParams = {
54
auth: {
@@ -14,7 +13,7 @@ jest.setTimeout(500000);
1413

1514
describe("long running request", () => {
1615
it("handles long request", async () => {
17-
const query = `SELECT checksum(*) FROM generate_series(1, 10000000000)`;
16+
const query = `SELECT checksum(*) FROM generate_series(1, 50000000000)`;
1817

1918
const firebolt = Firebolt({
2019
apiEndpoint: process.env.FIREBOLT_API_ENDPOINT as string
@@ -28,26 +27,22 @@ describe("long running request", () => {
2827
expect(data).toBeTruthy();
2928
expect(meta).toBeTruthy();
3029
});
31-
it("fails with timeout on network disconnect", async () => {
32-
const query = `SELECT checksum(*) FROM generate_series(1, 10000000000)`;
30+
it.skip("fails with timeout on network disconnect", async () => {
31+
const query = `SELECT checksum(*) FROM generate_series(1, 50000000000)`;
3332

3433
const firebolt = Firebolt({
3534
apiEndpoint: process.env.FIREBOLT_API_ENDPOINT as string
3635
});
3736

3837
const connection = await firebolt.connect(connectionParams);
3938

40-
setTimeout(() => {
41-
nock.disableNetConnect();
42-
}, 10000);
4339
try {
4440
const statement = await connection.execute(query);
45-
await statement.fetchResult();
46-
expect(true).toEqual(false);
41+
const { data, meta } = await statement.fetchResult();
42+
console.log(data);
4743
} catch (error) {
44+
console.log(error);
4845
expect(true).toEqual(true);
49-
} finally {
50-
nock.enableNetConnect();
5146
}
5247
});
5348
});

0 commit comments

Comments
 (0)