Skip to content

Commit 0032d75

Browse files
authored
fix: add keepalive agent timeout (#57)
1 parent b008309 commit 0032d75

File tree

6 files changed

+134
-13
lines changed

6 files changed

+134
-13
lines changed

package-lock.json

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

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,14 @@
2626
"@types/node-fetch": "^2.5.12",
2727
"@typescript-eslint/eslint-plugin": "^5.4.0",
2828
"@typescript-eslint/parser": "^5.4.0",
29+
"agentkeepalive": "^4.5.0",
2930
"dotenv": "^16.0.1",
3031
"eslint": "^8.2.0",
3132
"eslint-config-prettier": "^8.3.0",
3233
"eslint-plugin-prettier": "^4.0.0",
3334
"jest": "^27.5.1",
3435
"msw": "^0.45.0",
36+
"nock": "^13.3.6",
3537
"prettier": "^2.4.1",
3638
"standard-version": "^9.3.2",
3739
"ts-jest": "^27.0.7",

src/http/node.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { Agent } from "https";
1+
import { HttpsAgent } from "agentkeepalive";
2+
23
import Abort from "abort-controller";
34
import fetch from "node-fetch";
45
import { AbortSignal } from "node-fetch/externals";
@@ -37,7 +38,12 @@ export class NodeHttpClient {
3738
} {
3839
const { headers = {}, body, retry = true } = options || {};
3940
const controller = new AbortController();
40-
const agent = new Agent({ keepAlive: true, keepAliveMsecs: 1000 });
41+
const agent = new HttpsAgent({
42+
keepAlive: true,
43+
keepAliveMsecs: 1000,
44+
timeout: 60000,
45+
freeSocketTimeout: 30000
46+
});
4147

4248
const abort = () => {
4349
controller.abort();

src/statement/index.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import {
33
ExecuteQueryOptions,
44
StreamOptions,
55
Context,
6-
Statistics
6+
Statistics,
7+
Row
78
} from "../types";
89
import { Meta } from "../meta";
910
import { isDataQuery } from "../common/util";
@@ -161,12 +162,22 @@ export class Statement {
161162
};
162163
}
163164

164-
async fetchResult() {
165+
async fetchResult(): Promise<{
166+
data: Row[];
167+
meta: Meta[];
168+
statistics: Statistics | null;
169+
query_id?: string;
170+
}> {
165171
const response = await this.request.ready();
166172
const text = await response.text();
167173

168174
if (this.executeQueryOptions?.settings?.async_execution) {
169-
return JSONbig.parse(text);
175+
return JSONbig.parse(text) as {
176+
data: Row[];
177+
meta: Meta[];
178+
statistics: Statistics;
179+
query_id: string;
180+
};
170181
}
171182

172183
const parsed = this.handleParseResponse(text);

test/integration/index.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ describe("integration test", () => {
5858
});
5959
const { data } = await statement.fetchResult();
6060
const row = data[0];
61-
expect(row).toMatchObject({ "1": 1 });
61+
expect(row).toMatchObject({ "?column?": 1 });
6262
});
6363
it("async query", async () => {
6464
const firebolt = Firebolt({

test/integration/long.test.ts

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

34
const connectionParams = {
45
auth: {
@@ -12,21 +13,41 @@ const connectionParams = {
1213
jest.setTimeout(500000);
1314

1415
describe("long running request", () => {
15-
it.skip("handles long request", async () => {
16-
const query = `SELECT sleepEachRow(1) from numbers(360)`;
16+
it("handles long request", async () => {
17+
const query = `SELECT checksum(*) FROM generate_series(1, 10000000000)`;
1718

1819
const firebolt = Firebolt({
1920
apiEndpoint: process.env.FIREBOLT_API_ENDPOINT as string
2021
});
2122

2223
const connection = await firebolt.connect(connectionParams);
2324

24-
const statement = await connection.execute(query, {
25-
settings: { use_standard_sql: 0, advanced_mode: 1 }
26-
});
25+
const statement = await connection.execute(query);
2726

2827
const { data, meta } = await statement.fetchResult();
29-
expect(data.length).toEqual(360);
30-
expect(meta.length).toEqual(1);
28+
expect(data).toBeTruthy();
29+
expect(meta).toBeTruthy();
30+
});
31+
it("fails with timeout on network disconnect", async () => {
32+
const query = `SELECT checksum(*) FROM generate_series(1, 10000000000)`;
33+
34+
const firebolt = Firebolt({
35+
apiEndpoint: process.env.FIREBOLT_API_ENDPOINT as string
36+
});
37+
38+
const connection = await firebolt.connect(connectionParams);
39+
40+
setTimeout(() => {
41+
nock.disableNetConnect();
42+
}, 10000);
43+
try {
44+
const statement = await connection.execute(query);
45+
await statement.fetchResult();
46+
expect(true).toEqual(false);
47+
} catch (error) {
48+
expect(true).toEqual(true);
49+
} finally {
50+
nock.enableNetConnect();
51+
}
3152
});
3253
});

0 commit comments

Comments
 (0)