3

I'm using webpack hot module reload (hmr) for my nest.js application. The reload works but doesn't wait for the old instance to close fully (database connection, telegram bot,...) before starting up a new instance. This makes typeorm throw the following error:

AlreadyHasActiveConnectionError: Cannot create a new connection named "default", because connection with such name already exist and it now has an active connection session.

In my main.ts I have a dispose handler that closes the old instance:

if (module && module.hot) {
  module.hot.accept();
  module.hot.dispose(async () => {
    console.log('disposing module');
    await app.close();
    console.log('has closed app');
  });
}

When I run hmr and make a change to my app, I can see that it calls the dispose handler and immediately starts up the new application. How can I make webpack wait for the promise to resolve that is returned by the dispose handler before starting the new instance?

Kim Kern
  • 54,283
  • 17
  • 197
  • 195
  • What if you call `accept` in `dispose`'s callback, _after_ the `await`? – Stock Overflaw Feb 23 '19 at 15:17
  • From one noob to another... ;-) Yes, I've tried that already and unfortunately, this doesn't work. It will fail on the initial start because the module has to `accept` itself even before a change happens. Also, I think it starts the application first and then `accepts` itself. I'm afraid that hmr just isn't intended to wait (it's supposed to be quick right?! ;)) So the solution probably is to handle all the resources that can only be acquired once as is possible for the database connection. Now I have to figure out how to handle my bot... Thanks for your help anyway. :) – Kim Kern Feb 23 '19 at 15:48
  • _fail on the initial start_: if you think only the first pass would fail, then it's possible to flag the calls? Something like `if (!m.hot.hasDispose) m.hot.accept();` then in the callback `m.hot.accept(); m.hot.hasDispose = true;`? (Or maybe use another object to hold the flag, no idea whether this `module.hot` persists.) Anyway, good luck, it's weird that no one seems to have addressed this issue without altering lower layers like this `TypeOrm` workaround... – Stock Overflaw Feb 23 '19 at 16:35
  • Hi, ever found a solution to this? I run into a similar issue with Apollo Universal Starter Kit when startup takes to much time, I get an EADDRINUSE when the new server starts so I guess the first one is not actually closed ([code here](https://github.com/sysgears/apollo-universal-starter-kit/blob/stable/modules/core/server-ts/server.ts)) – Eric Burel Jun 14 '19 at 07:59
  • @EricBurel I'm afraid not, for typeorm the `keepConnectionAlive` helped, in the other case it's just a log message that I'm ignoring. Maybe you can find a similar option in your case. I don't think there is a generic solution available. – Kim Kern Jun 14 '19 at 09:12
  • Hi, eventually the issue for me was using Yarn 0.12.x, which has issues with children signals. So the `module.hot.dispose` callback was not even called in the first place. – Eric Burel Jun 17 '19 at 06:14

1 Answers1

7

According to this issue, you can set keepConnectionAlive to true in the typeorm options for it to reuse the connection.

TypeOrmModule.forRoot({
  // ...
  keepConnectionAlive: true,
})

This does solve the typeorm error but the problem with the telegram bot persists:

Error: 409: Conflict: terminated by other getUpdates request; make sure that only one bot instance is running

I don't think I can reuse the bot instance, so this is only a partial solution.

Kim Kern
  • 54,283
  • 17
  • 197
  • 195