TypeORM with MySQL Error: Pool is closed. Test is getting stuck when calling the Database

Viewed 4397

we're having a weird issue with TypeORM, specifically with Jest(might be related, might not be). A certain test is getting completely stuck/hung and we’re having a hard time figuring out what the issue is.

In terms of stack: Typescript, NodeJS, Apollo Graphql, Jest, MySQL. The test in question is actually an integration test using Apollo’s integration test framework.

What happened first is that a specific test just completely got stuck, and after several long minutes an error is thrown in the console: QueryFailedError: ER_LOCK_WAIT_TIMEOUT: Lock wait timeout exceeded; try restarting transaction

Trying to pinpoint the problem led me to a function we run on afterEach which “destroys” the database. It initially ran:

await queryRunner.query('DELETE FROM Table1');
await queryRunner.query('DELETE FROM Table2');
...

The error and "deadlock" was initially fixed after I changed it from queryRunner to queryBuilder:

await queryBuilder.delete().from('Table1').execute();
...

This was done after fidgeting around with SHOW PROCESSLIST; and with SHOW ENGINE InnoDB STATUS; to try figuring out what was happening. I also changed the transaction isolation to READ-COMMITTED but to no avail. Nothing really worked except changing it from queryRunner to queryBuilder.

This worked for a bit but now it seems like the test is getting stuck again (The test hasn’t changed but the code it’s testing has). Now after the test hangs, we get this error: Error: Pool is closed. Afterwards the test is "released" and all the tests just start failing one by one.

We found out that this is the sequence of events that causes the test to get stuck:

1. open a transaction with queryRunner
2. perform a read query
3. then perform a write
4. commit the transaction and release the queryRunner
5. delete the DB
6. perform a write - deadlock

Furthermore we noticed the following:

If we make sure that we only use the queryRunner for updates, and not for queries, then the deadlock doesn’t happen.

Changing the code such that we first make all of the read queries with the regular connection object (not queryRunner) and only then if we connect with queryRunner and make all of the writes - then the deadlock does not happen.

Does anyone have any insight as to what might be going on? Is there some instability with queryRunner or some specific things we need to take into account when using it?

Thanks!

1 Answers

I was faced same issue and my problem was unhandled async/await. Check if some promise object is not handled. If you use async keyword, you must handle all async functions using await keyword. Also don't forget calling done method of jest.

Related