raveljs / ravel

Forge past a tangle of node.js modules. Make a cool app.
http://raveljs.github.io/docs/latest/
MIT License
21 stars 6 forks source link

Prelisten decorator does not wait for completion of async methods during `app.listen` call #315

Closed ggayowsky closed 3 years ago

ggayowsky commented 3 years ago

I am not sure if this is a bug or desired behaviour, however, when using an async function decorated with the @prelisten decorator (which is used to run a method on a module during on the pre listen stage on the Ravel start up methods), the functions are non-blocking and thus the await ravelInstance.listen() will complete before all @prelisten methods have completed.

e.g.

@Module
class TestClass {
  @prelisten
   async doSomething () {
     await someAsyncFunction();
     console.log('This will log AFTER the `await ravelInstance.listen()` has returned');
   }
}

IMO, this is a bug, because injecting the ravel instance and the manual registering the same function to the pre listen event will block.

@Module
@inject('$app')
class TestClass2 {
  constructor (ravelApp) {
    ravelApp.once('pre listen', this.doSomething.bind(this));
  }

  async doSomething () {
     await someAsyncFunction();
     console.log('This will log BEFORE the `await ravelInstance.listen()` has returned');
  }
}

To further this, I believe none of the @postinit, @prelisten, @koaconfig, @postlisten and @preclose decorators block the completion of init / listen. This is because the listener passed in the once function in the connectHandlers method (which sets up the callback for the decorators) (https://github.com/raveljs/ravel/blob/2971972e025f5d5167181b8c2f8358b00f9126f8/lib/core/module.js#L24) does not await on the decorated function

Ghnuberath commented 3 years ago

Yup, definitely a bug. I noticed this last week as well while wiring up a simple app where I needed a @prelisten to finish before the app actually accepted connections (and it didn't work haha).