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

Microservice client registration in dynamicaly configured module for nest.js and loading into service by parameter

我在应用程序中使用了具有动态配置的 shared 模块。 共享模块包含 interceptorservice,其中包含从共享参数配置的客户端。 我通过预定义的名称将 service 注入到 interceptor 中(将 SharedModule 动态导入到 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);
    }
}

问题

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

我在列表中检测到两种方法可以将过去的名称作为参数投入使用,而不会破坏由 nest.js 管理的 DI。但是我不知道如何通过指定名称访问模块上下文以加载服务(想法片段的代码如下)

@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

// ...
}

P.S.

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

git code

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

第一个选项

在模块配置级别:

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

@Module({
  imports: [
    ClientModule.register([
      { 'NAME_FOR_DI', ...configForYourClient }
    ])
  ],
...
})
...

用法:

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

...
  constructor(@Inject('NAME_FOR_DI') private readonly client:   ClientProxy) { }

第二个选项

对于动态配置的模块:

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)

按照第二个选项,它可以直接在服务中创建,也可以在提供程序中为指定 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)
    },
  ],
...
})
...

通过指定键进行后续注入。

P.S.

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