微服务客户端在 Nest.js 的动态配置模块中注册并通过参数加载到服务中

Ser*_*gii 2 ioc-container microservices nestjs

shared在应用程序中使用了具有动态配置的模块。共享模块包含interceptorservice其中包含从共享参数配置的客户端。我通过预定义名称将 注入service到 中interceptorSharedModule动态导入到 中SecondAppModule)。所以客户名称可以有不同的值。在服务内部,我需要在客户端注入之前知道客户端的名称。现在它是硬编码的:

@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);
    }
}

Run Code Online (Sandbox Code Playgroud)

问题

如果名称仅在构造时已知,是否有任何方法可以按名称从上下文加载服务?

我在列表中检测到两种方法可以将名称作为参数传递到服务中,而不会破坏nest.js. 但我不知道如何访问模块上下文以按指定名称加载服务(想法片段的代码如下)

@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

// ...
}
Run Code Online (Sandbox Code Playgroud)

聚苯乙烯

这个想法是在同一个应用程序中使用多个客户端。我第一次考虑每个模块一个客户端的场景。

git代码

Ser*_*gii 5

在动态模块中创建微服务客户端的选项很少:

第一个选项

在模块配置级别:

import { Module } from '@nestjs/common';
import { ClientModule } from '@nestjs/microservices';
import { configForYourClient } from '../configs';

@Module({
  imports: [
    ClientModule.register([
      { 'NAME_FOR_DI', ...configForYourClient }
    ])
  ],
...
})
...
Run Code Online (Sandbox Code Playgroud)

用法:

import { Inject } from '@nestjs/common';
import { ClientProxy } from '@nestjs/microservices';

...
  constructor(@Inject('NAME_FOR_DI') private readonly client:   ClientProxy) { }
Run Code Online (Sandbox Code Playgroud)

第二个选项

对于动态配置的模块:

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 }
        ])
      ],
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

第三个选项

import { ClientProxy, ClientProxyFactory } from '@nestjs/microservices';
import { configForYourClient } from '../configs';

...
  private client: ClientProxy = ClientProxyFactory.create(configForYourClient)
Run Code Online (Sandbox Code Playgroud)

按照第二个选项,它可以直接在服务中创建,也可以注册到提供程序中指定 DI 密钥的模块,例如:

import { Module } from '@nestjs/common';
import { ClientProxyFactory } from '@nestjs/microservices';
import { configForYourClient } from '../configs';

@Module({
  providers: [
    {
      provide: 'NAME_FOR_DI',
      useValue: ClientProxyFactory.create(configForYourClient)
    },
  ],
...
})
...
Run Code Online (Sandbox Code Playgroud)

通过指定的键进行以下注入。

聚苯乙烯

我在这里描述了动态注入的一般思想。这个想法可以通过不同的组合来丰富(注入单个提供者的值列表,或者将配置列表注入到ClientModule.register您应该在 DI 方法中应用一些更正的地方)