Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open Knex database causes open handles issues in Jest 27 #11463

Open
joshkel opened this issue May 27, 2021 · 7 comments
Open

Open Knex database causes open handles issues in Jest 27 #11463

joshkel opened this issue May 27, 2021 · 7 comments

Comments

@joshkel
Copy link
Contributor

joshkel commented May 27, 2021

馃悰 Bug Report

If a test creates an in-memory SQLite3 Knex database and doesn't destroy it, then Jest 27 hangs with the following error:

Jest did not exit one second after the test run has completed.

This usually means that there are asynchronous operations that weren't stopped in your tests. Consider running Jest with --detectOpenHandles to troubleshoot this issue.

If I run with --detectOpenHandles, then Jest doesn't print any messages, but it still hangs once the tests have finished.

(This is the same issue as #9473, but it occurs in Jest 27.)

This issue only happens in Jest 27. In Jest 26 and jest-circus 26, Jest cleanly exits with no warnings.

To Reproduce

Steps to reproduce the behavior: Clone the https://github.com/joshkel/jest-knex-open-handles repository and run npm i && npm test

Downgrade to Jest 26 and note that it cleanly exits: npm i jest@^26 jest-circus@^26 && npm test

Expected behavior

Jest cleanly exits; or, if Jest doesn't cleanly exit because of the open database, then --detectOpenHandles should explain the problem.

Link to repl or repo (highly encouraged)

https://github.com/joshkel/jest-knex-open-handles

envinfo

  System:
    OS: macOS 11.4
    CPU: (8) x64 Intel(R) Core(TM) i7-4980HQ CPU @ 2.80GHz
  Binaries:
    Node: 12.18.3 - ~/.nvm/versions/node/v12.18.3/bin/node
    Yarn: 1.22.10 - /usr/local/bin/yarn
    npm: 6.14.8 - ~/.nvm/versions/node/v12.18.3/bin/npm
  npmPackages:
    jest: ^27.0.1 => 27.0.1 
@joshkel
Copy link
Contributor Author

joshkel commented May 28, 2021

Running wtfnode shows that a timer from Knex's Tarn connection pool is what's keeping Jest from exiting:

[WTF Node?] open handles:
- File descriptors: (note: stdio always exists)
  - fd 1 (tty) (stdio)
  - fd 2 (tty) (stdio)
  - fd 0 (tty)
- Intervals:
  - (1000 ~ 1000 ms) (anonymous) @ /Users/joshkelley/src/jest-workspace/jest-knex-open-handles/node_modules/tarn/dist/Pool.js:451

Jest should probably show non-user-created resources to help troubleshoot issues like this; see this comment. (In other words, these two issues may be at least partial duplicates.)

@kratos-42
Copy link

Similar behaviour occurs when a redis connection is still open.
Using jest@26.4.0 version with options jest --findRelatedTests --runInBand --detectOpenHandles --forceExit it forces redis to exit/disconnect; after upgrading to jest@27.x.x, Jest complains about redis process potentially keeping it from exiting.

@github-actions
Copy link

This issue is stale because it has been open for 1 year with no activity. Remove stale label or comment or this will be closed in 30 days.

@github-actions github-actions bot added the Stale label Apr 20, 2023
@natevw
Copy link

natevw commented May 18, 2023

Has anyone found a great workaround for this? I found that I can call knex.destroy() in my "last" test to prevent this, but that's not a real elegant or maintainable solution since if Jest ends up running any other tests after the one I assumed would be last one to use knex, they end up failing kind of cryptically because their connection is unexpectedly broken.

@github-actions github-actions bot removed the Stale label May 18, 2023
@kratos-42
Copy link

I found that I can call knex.destroy() in my "last" test to prevent this, but that's not a real elegant

Have you tried using global teardown?

@natevw
Copy link

natevw commented May 19, 2023

Have you tried using global teardown?

Thanks, I think that's a near-perfect fit! Unfortunately pointing globalTeardown: './jest.teardown.ts' to a file like this:

import { knex } from "./knex/sharedConnection";

module.exports = async function () {
  await knex.destroy();
};

does not work in practice in our case because the "sharedConnection" module ends up not actually being fully shared for some reason! (i.e. the instance that gets .destroy() called on it here is not the same instance that the tests were using.) My assumption is that's on us and not a Jest-specific issue though.

@kratos-42
Copy link

If that is a shared knex instance it should do the job.
Why do you say it's not working? Is the exported function being triggered?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants