@@ -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 ,
0 commit comments