JimmyTheCode
JimmyTheCode

Reputation: 5714

Jest TLSWRAP open handle error using simple node-postgres pool.query() fixed with setTimeout delay, but why?

When I run the following test:

afterAll(async () => {
    await runDbBuild();
    await pool.end();
});

describe("queries.newteetypes.select.all():", () => {
        test("Test 1: object keys ", async () => {
            const awaitedResponse = await queries.newteetypes.select.all();
            expect(awaitedResponse).toStrictEqual(anticipatedResponse);
    });
});

I get this error: Jest has detected the following 1 open handle potentially keeping Jest from exiting: screenshot of error

The above code that is shown works absolutely fine in production. The issue is only with jest giving me a potential open handles warning.

I can fix it by introducing a delay with a setTimeout() and Promise, but the placement baffles me. Here's the solution (same code but with one line added above the query call):

afterAll(async () => {
    await runDbBuild();
    await pool.end();
});

describe("queries.newteetypes.select.all():", () => {
        test("Test 1: object keys ", async () => {
            await new Promise((resolve) => setTimeout(() => resolve(), 2000)); // Putting a delay before the query solves the problem, but putting the delay after the query doesn't resolve it.
            const awaitedResponse = await queries.newteetypes.select.all();
            expect(awaitedResponse).toStrictEqual(anticipatedResponse);
    });
});

This seems very counter-intuitive to me. Initially I tried putting the timeout in the afterAll() function, but it didn't make any difference no matter where I included it. So then I experimented by putting it after the query call, within the test() function, but that didn't work. When I put it before the query call, I stop receiving the error. But why would that make a difference?

Upvotes: 6

Views: 3497

Answers (1)

alfreema
alfreema

Reputation: 1338

Treat your "new Pool( ...)" as a promise and await for it:

async function createPool () {
  return await new Pool({ connectionString })
}

Your findings of setTimeout, had me try this with the same successful result:

await process.nextTick(() => {})

Placing that right before my connect() worked. So from there I started backing up to the "earliest" point that adding a process.nextTick would fix the issue and it appears to be solved by just treating new Pool(..) as a promise.

Perhaps the pool is willing to start dishing out clients before it's completely ready to track them under the hood? That might be why the extra await up front solves this.

This could very much be related to why people are not able to close clients or the pool properly -- because something about the pool management is mangled. For example: https://github.com/brianc/node-postgres/issues/2341

Upvotes: 8

Related Questions