nest
nest copied to clipboard
Feat: onApplicationReady Hook
Is there an existing issue that is already proposing this?
- [X] I have searched the existing issues
Is your feature request related to a problem? Please describe it
There are a lot of potential tasks that can be done successfully only after the start of an application (when the app is ready to handle connections).
The onApplicationBootstrap triggers before await app.listen(), so it can't be used for such tasks (correct me if I'm wrong).
Describe the solution you'd like
Although this can be easily implemented using events, another good option would be introducing a new hook that triggers after await app.listen().
Teachability, documentation, adoption, migration strategy
The hook's name can be onApplicationReady or onApplicationStart. The usage of the hook will be pretty similar to the other hooks:
export class CustomProvider implements OnApplicationReady {
onApplicationReady(): void {
console.log('Ready!')
}
}
What is the motivation / use case for changing the behavior?
One of the use cases could be webhook subscriptions. When I subscribe to webhooks, the publisher sends me a POST request to verify my webhook callback. It is safer to perform this task after the application is ready to listen for connections.
+1 support Is this feature being considered by the NestJs team?
I'm not sure about the naming and the role of that hook. I'd need to think more about it. But I can say that maybe we need a more specific name because 'ready' can be interpreted in several ways
You can supply a callback already to app.listen method but I get that you want to make things more coupled with nestjs providers and modules; more high-level
I'm not sure about the naming and the role of that hook. I'd need to think more about it. But I can say that maybe we need a more specific name because 'ready' can be interpreted in several ways
You can supply a callback already to
app.listenmethod but I get that you want to make things more coupled with nestjs providers and modules; more high-level
@micalevisk Maybe something like onApplicationInit
'init' would be confusing because we have app.init()
What about using https://docs.nestjs.com/techniques/events and then
await app.listen(...);
await app.get(EventEmitter2).emit(...);
Done(?) This gives you full control too
@kamilmysliwiec I personally already use this approach. It just feels like this functionality should be available out of the box with the rest of the hooks and have similar usage. Without this hook, lifecycle hooks feel incomplete.
The thing is, onApplicationReady is just somewhat vague as "ready" might mean different things depending on the context. For some, it's just that the app is already listening to HTTP requests, but for those who have hybrid applications (HTTP + message broker) the definition is probably going to be different. Not to mention that those who use the "Standalone application" mode wouldn't use that hook at all.
Yeah, I didn't take those things into account when I came up with the hook name. Naming is not my strong point :) There's a lot to think about here. You guys know better anyway.
I'm also interested by this feature. I have been using NestJS as my backend framework for years and I'd love to contribute to NestJS.
The thing is,
onApplicationReadyis just somewhat vague as "ready" might mean different things depending on the context. For some, it's just that the app is already listening to HTTP requests, but for those who have hybrid applications (HTTP + message broker) the definition is probably going to be different. Not to mention that those who use the "Standalone application" mode wouldn't use that hook at all.
@kamilmysliwiec I think it would make sense to name the lifecycle "events" related to the methods we use to bootstrap a NestJS app:
const app = await NestFactory.create(AppModule);
// Triggers the method `onApplicationCreated` of all `OnApplicationCreated` implementations
await app.listen(...);
// Triggers the method `onApplicationListening` of all `OnApplicationListening` implementations.
What do you think of these namings?
On another subject, I'd like to react to this comment:
What about using https://docs.nestjs.com/techniques/events and then
await app.listen(...); await app.get(EventEmitter2).emit(...);Done(?) This gives you full control too
I am not a big fan of EventEmitter2 but I have been implementing in by own synchronous event bus (with handlers priority management) in my backends for some time and it would really be awesome if NestJS had an internal event bus we could subscribe to when we need it.
Having both onApplication[...] hooks and an event bus would give us much more freedom in how we want to architect our application code.
I would also love to provide a PR with an implementation of it in NestJS so we can discuss about it together if you're interested.
@SylvainMarty as we can do app.init() without listen, the 'on application created' name would be confusing
I still have no ideia about the naming of this
@micalevisk Thank you for your answer.
I'm not familiar with the await app.init() method but from its documentation, it's an optional method that calls the Nest lifecycle events. From the source code, calling await app.listen() actually calls await app.init() in the background.
To me, it would be useful to have the following lifecycle events:
await NestFactory.create(AppModule)->OnApplicationCreatehooks are calledawait app.init()->OnApplicationInithooks are called (previously calledOnApplicationBootstrap, we could keep the old hook to avoid introducing breaking change)- If
await app.listent()is called ->OnApplicationListenhooks are called - Using the listen method or not, the more general purpose hooks
OnApplicationStartare called
About the method await app.startAllMicroservices(): since it calls await mc.listen() of the connected microservice, the lifecycle events would follow the said lifecycle for each microservice.
Let me know what you think of this.
Looks good so far but I guess we won't rename nor change/deprecate existing hooks anytime soon
I was looking into liveness/readiness indicators for Kubernetes (via Terminus). And found some events, such as the proposal here as being required to properly manage the probe states. I also develop Spring Boot apps and there are a lot of comparable patterns provided by that framework.
Specifically re: application events, Spring provides a set of application events that include what is being requested here, so that may be useful to compare the definitions they use.
A direct use-case for this ApplicationReadyEvent (Spring's equivalent) would allow for the readiness indicator to be determined via same logic as Spring, which is something I would like to make happen in my apps. Manually updating the readiness state after await app.listen(...) (as others have shared) is how I have approached it up to this point.
Ultimately the number of Nest's lifecycle events are somewhat finite, but I wonder if producing them via an emitter/filterable listeners as opposed to distinct hook methods could be easier/more scalable?
Some related links re: Kubernetes probes:
- https://docs.spring.io/spring-boot/reference/features/spring-application.html#features.spring-application.application-availability
- https://docs.spring.io/spring-boot/reference/actuator/endpoints.html#actuator.endpoints.kubernetes-probes
Let's track this here https://github.com/nestjs/nest/pull/14143