Nest: Make Microservice creation dependent on the ApplicationContext

Created on 5 Jun 2019  路  6Comments  路  Source: nestjs/nest

Feature Request

Is your feature request related to a problem? Please describe.

I believe that the way Nestjs is bootstraped could be improved by allowing the definition of the container before the definition of the application.

Take as an example a ConfigService that would read all the variables in .env in order to use them as options to define a new Nestjs Microservice while having the following code, how would you do it?

async function bootstrap() {
    const app = await NestFactory.createMicroservice(AppModule, {
        transport: Transport.RMQ,
        options: {
            urls: [
                'amqp://guest:guest@localhost:5672',
            ],
            queue: 'test',
            queueOptions: { durable: true },
        },
    });
    ...
}

At the moment only 2 solutions come in mind:

  • define an ApplicationContext to be able to get the ConfigService from the container to use it for instantiating the microservice.
  • define a service that should be instantiated manually before without DependencyInjection

Describe the solution you'd like

I believe that this could be done by instantiating the ApplicationContext that loads up the Container and then use the ApplicationContext as a parameter for the NestFactory.createMicroservice method.

Teachability, Documentation, Adoption, Migration Strategy

In order to support backwards compatibility you could even allow both the current way in case the paramenter a Module or the following one in case it is an instance of an ApplicationContext

async function bootstrap() {
    const app = await NestFactory.createApplicationContext(AppModule);

    const config = app.get(ConfigService);

    const microservice = await NestFactory.createMicroservice(app, {
        transport: Transport.RMQ,
        options: {
            urls: [
                config.amqpUrl,
            ],
            queue: config.queue,
            queueOptions: { durable: true },
        },
    });
    ...
}

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

  • I believe this could improve the quality of the code.
  • Could be useful in order to add a single instance of a LoggerService via DependecyInjection and also allow setting config options on it in order to call external services like Logstash etc.
type

Most helpful comment

@kamilmysliwiec is this a planned feature?

All 6 comments

@kamilmysliwiec is this a planned feature?

I found this solution ->

const app = await NestFactory.create(AppModule, {
    logger: new Logger(),
})
const configService = app.get<ConfigService>(ConfigService)
app.connectMicroservice<MicroserviceOptions>({
    transport: Transport.RMQ,
    options: {
        urls: [amqp://${configService.get<string>('rabbitmq.host')}:${configService.get<number> 
         ('rabbitmq.port')}],
        queue: 'authentication',
        queueOptions: {
              durable: false,
          },
    },
})
app.startAllMicroservices(() => {
logger.log('Microservice is listening...')
})

this is work (usual MICROSERVICES) ! but this appear not work for websockets

I`m implementing Nest.js powered microservice and I need to do two things. Firstly, I need to get a configuration service in my main.ts file, and pass it as a constructor param to a custom transport strategy. Secondly, I need to do some bootstrapping actions in my service after microservice was bootstrapped.
The issue I faced seems related to this issue: when I`m using app = await NestFactory.create(AppModule) and then app.connectMicroservice({strategy: myCustomStrategy}) - _onApplicationBootstrap_ event has not fired. But when I`m using appContext = await NestFactory.createApplicationContext(AppModule) and then microservice = await NestFactory.createMicroservice(appContext, {strategy: myCustomStrategy}) - there is an error 'metatype is not a constructor' raised at _NestFactoryStatic.createMicroservice._
So for now I don`t understand, how I can pass correct environment config and catch the bootstrapping event simultaneously. Please, help me to figure out, if it can be done somehow.

I found this solution ->

const app = await NestFactory.create(AppModule, {
    logger: new Logger(),
})
const configService = app.get<ConfigService>(ConfigService)
app.connectMicroservice<MicroserviceOptions>({
    transport: Transport.RMQ,
    options: {
        urls: [amqp://${configService.get<string>('rabbitmq.host')}:${configService.get<number> 
         ('rabbitmq.port')}],
        queue: 'authentication',
        queueOptions: {
              durable: false,
          },
    },
})
app.startAllMicroservices(() => {
logger.log('Microservice is listening...')
})

this is work (usual MICROSERVICES) ! but this appear not work for websockets

The one bit that becomes a sticking point with this example is that lifecycle methods do not work.

I found this solution ->

const app = await NestFactory.create(AppModule, {
    logger: new Logger(),
})
const configService = app.get<ConfigService>(ConfigService)
app.connectMicroservice<MicroserviceOptions>({
    transport: Transport.RMQ,
    options: {
        urls: [amqp://${configService.get<string>('rabbitmq.host')}:${configService.get<number> 
         ('rabbitmq.port')}],
        queue: 'authentication',
        queueOptions: {
              durable: false,
          },
    },
})
app.startAllMicroservices(() => {
logger.log('Microservice is listening...')
})

this is work (usual MICROSERVICES) ! but this appear not work for websockets

The one bit that becomes a sticking point with this example is that lifecycle methods do not work.

Yes, but you can call the app.init method manually

  app.startAllMicroservices(async () => {
    // Calls the Nest lifecycle events.
    await app.init()
    logger.log('Microservice is listening...')
  })

Is this gonna be solved or stay this way with the current workarounds, in my opinion this is pretty trivial usage

Was this page helpful?
0 / 5 - 0 ratings

Related issues

hackboy picture hackboy  路  3Comments

mishelashala picture mishelashala  路  3Comments

anyx picture anyx  路  3Comments

rlesniak picture rlesniak  路  3Comments

menme95 picture menme95  路  3Comments