I used shared
module with dynamic configuration in application.
Shared module contains interceptor
and service
which contains client configured from shared parameters.
I injected the service
into the interceptor
by predefined name (importing SharedModule
dynamically into SecondAppModule
). So client name can have different value. Inside of service I need to know the clients name before client injecting. Right now it is hard coded:
@Injectable()
export class SumClientService {
constructor(@Inject('MATH_SERVICE') private client: ClientProxy) {
console.log('[SumClientService] - created')
}
sumCalculation(row: number[]): Observable<number> {
return this.client.send<number>({ cmd: 'sum' }, row);
}
}
Is there any ways to load service from context by name in case name known at construction time only?
I've detected two ways at list to past name as a parameter into service without corrupting DI managed by nest.js
. But I have no idea how to get access to module context for loading service by specified name (the code of idea fragment is below)
@Injectable()
export class SumClientService {
constructor(@Inject('service_name') private name: string) {
console.log('[SumClientService] - created')
}
client: (clientName: string) => ClientProxy = (clientName: string): ClientProxy => // TODO load by clientName real client from `nest.js` context
// ...
}
The idea is to use multiple clients in the same application. I considered scenario one client per module for the first time.
There are few options to create microservice clients in dynamic module:
in module configuration level:
import { Module } from '@nestjs/common';
import { ClientModule } from '@nestjs/microservices';
import { configForYourClient } from '../configs';
@Module({
imports: [
ClientModule.register([
{ 'NAME_FOR_DI', ...configForYourClient }
])
],
...
})
...
usage:
import { Inject } from '@nestjs/common';
import { ClientProxy } from '@nestjs/microservices';
...
constructor(@Inject('NAME_FOR_DI') private readonly client: ClientProxy) { }
For dynamically configured module:
import { Module, DynamicModule } from '@nestjs/common';
import { ClientModule } from '@nestjs/microservices';
import { configForYourClient } from '../configs';
@Module({})
export class YourModule{
static register(): DynamicModule {
return {
module: YourModule,
imports: [
ClientModule.register([
{ 'NAME_FOR_DI', ...configForYourClient }
])
],
}
}
}
import { ClientProxy, ClientProxyFactory } from '@nestjs/microservices';
import { configForYourClient } from '../configs';
...
private client: ClientProxy = ClientProxyFactory.create(configForYourClient)
Following second option it can be created in service directly or registered for module specifying DI key in providers, like:
import { Module } from '@nestjs/common';
import { ClientProxyFactory } from '@nestjs/microservices';
import { configForYourClient } from '../configs';
@Module({
providers: [
{
provide: 'NAME_FOR_DI',
useValue: ClientProxyFactory.create(configForYourClient)
},
],
...
})
...
with following injection by specified key.
I've described here general idea for dynamic injection. This idea can be enriched with different combinations (injecting list of values for the single provider, or injecting list of configurations into ClientModule.register
where you should apply some corrections in you DI approach)