Skip to content

Commit 69d88b8

Browse files
Performance fixes (#207)
* Fix event loop blocking Signed-off-by: Levko Kravets <levko.ne@gmail.com> * Increase connection pool when using CloudFetch Signed-off-by: Levko Kravets <levko.ne@gmail.com> --------- Signed-off-by: Levko Kravets <levko.ne@gmail.com>
1 parent 9b03de3 commit 69d88b8

2 files changed

Lines changed: 22 additions & 1 deletion

File tree

lib/DBSQLOperation/index.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,24 @@ export default class DBSQLOperation implements IOperation {
147147
const resultHandler = await this.getResultHandler();
148148
await this.failIfClosed();
149149

150+
// All the library code is Promise-based, however, since Promises are microtasks,
151+
// enqueueing a lot of promises may block macrotasks execution for a while.
152+
// Usually, there are no much microtasks scheduled, however, when fetching query
153+
// results (especially CloudFetch ones) it's quite easy to block event loop for
154+
// long enough to break a lot of things. For example, with CloudFetch, after first
155+
// set of files are downloaded and being processed immediately one by one, event
156+
// loop easily gets blocked for enough time to break connection pool. `http.Agent`
157+
// stops receiving socket events, and marks all sockets invalid on the next attempt
158+
// to use them. See these similar issues that helped to debug this particular case -
159+
// https://github.com/nodejs/node/issues/47130 and https://github.com/node-fetch/node-fetch/issues/1735
160+
// This simple fix allows to clean up a microtasks queue and allow Node to process
161+
// macrotasks as well, allowing the normal operation of other code. Also, this
162+
// fix is added to `fetchChunk` method because, unlike other methods, `fetchChunk` is
163+
// a potential source of issues described above
164+
await new Promise<void>((resolve) => {
165+
setTimeout(resolve, 0);
166+
});
167+
150168
const result = resultHandler.fetchNext({
151169
limit: options?.maxRows || defaultMaxRows,
152170
disableBuffering: options?.disableBuffering,

lib/connection/connections/HttpConnection.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,12 @@ export default class HttpConnection implements IConnectionProvider {
4848

4949
private getAgentDefaultOptions(): http.AgentOptions {
5050
const clientConfig = this.context.getConfig();
51+
52+
const cloudFetchExtraSocketsCount = clientConfig.useCloudFetch ? clientConfig.cloudFetchConcurrentDownloads : 0;
53+
5154
return {
5255
keepAlive: true,
53-
maxSockets: 5,
56+
maxSockets: 5 + cloudFetchExtraSocketsCount,
5457
keepAliveMsecs: 10000,
5558
timeout: this.options.socketTimeout ?? clientConfig.socketTimeout,
5659
};

0 commit comments

Comments
 (0)