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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: Hierarchical module resolution #938

Closed
aigoncharov opened this issue Aug 2, 2018 · 7 comments
Closed

Proposal: Hierarchical module resolution #938

aigoncharov opened this issue Aug 2, 2018 · 7 comments

Comments

@aigoncharov
Copy link

I'm submitting a...


[ ] Regression 
[ ] Bug report
[x] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

Current behavior

Currently all lifecycle hooks run asynchronously, regardless of their importing order. If any module depends on an async provider it has to import a module this provider belongs to and then import the provider itself to wait for it being resolved.

Expected behavior

It feels natural for any module to wait for its dependencies' initialization before its own initialization. I propose to build a hierarchy of modules and resolve the resulting tree starting from its children. It should work in reverse with module destruction. First top level modules are destroyed, then children.

const sleep = (time: number) => new Promise((resolve, reject) => setTimeout(resolve, time))

@Module()
class B  implements OnModuleInit, OnModuleDestroy  {
  public async onModuleDestroy () {
    await sleep(1000)
    console.log('B destroyed')
  }
  public async onModuleInit () {
    await sleep(1000)
    console.log('B initialized')
  }
}

@Module({
  imports: [ B ]
})
class A  implements OnModuleInit, OnModuleDestroy  {
  public async onModuleDestroy () {
    await sleep(1000)
    console.log('A destroyed')
  }
  public async onModuleInit () {
    await sleep(1000)
    console.log('A initialized')
  }
}

I want Nest to guarantee that when A is created B.onModuleInit runs before A.onModuleInit and when it's destroyed that A.onModuleDestroy runs before B.onMOduleDestroy

What is the motivation / use case for changing the behavior?

Imagine your application having ThirdPartyLib module. It calls function thirdPartyLibInit using FFI to initialize a C-callable library on creation. Imagine your application having controller MyController depending on ThirdPartyLib. It can not function properly without that C-callable library initialized. Now you have to create an async factory that makes that FFI call and inject it everywhere. It's not very clean. I'd like to be able to import ThirdPartyLib into MyController and leave it up to Nest to figure it out.

@aigoncharov
Copy link
Author

Relates to #550

@kamilmysliwiec
Copy link
Member

solved by #977

kamilmysliwiec added a commit that referenced this issue Aug 16, 2018
feature(@nestjs/core) add hierarchical lifecycle hooks #938
@aigoncharov
Copy link
Author

@kamilmysliwiec you are the man! Thank you!

@kamilmysliwiec
Copy link
Member

Thanks! Gonna leave it open until 5.2.0 is published :)

@kamilmysliwiec
Copy link
Member

5.2.0 is here!

@jBouyoud
Copy link

As I experiment lifecycle event are not called in special order (before all non global modules for OnModuleInit, after all non global modules for OnModuleDestroy).
It is an intent or a bug, I don't find anything in our doc about global module and lifecycle event ?

Thanks

@lock
Copy link

lock bot commented Oct 22, 2019

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@lock lock bot locked as resolved and limited conversation to collaborators Oct 22, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants