mirror of
https://github.com/nestjs/nest.git
synced 2026-02-21 23:11:44 +00:00
feat: allow for microservice options to come from the di container
Microservices are now able to be created by getting their options from within the DI container itself. This has been a long requested feature of developers and I finally had some time to work through how we could possibly let this happen.
This commit is contained in:
98
integration/microservices/e2e/sum-rpc-async.spec.ts
Normal file
98
integration/microservices/e2e/sum-rpc-async.spec.ts
Normal file
@@ -0,0 +1,98 @@
|
||||
import {
|
||||
Controller,
|
||||
INestMicroservice,
|
||||
Injectable,
|
||||
Module,
|
||||
} from '@nestjs/common';
|
||||
import {
|
||||
AsyncOptions,
|
||||
ClientTCP,
|
||||
ClientsModule,
|
||||
MessagePattern,
|
||||
MicroserviceOptions,
|
||||
Payload,
|
||||
TcpClientOptions,
|
||||
Transport,
|
||||
} from '@nestjs/microservices';
|
||||
import { expect } from 'chai';
|
||||
import { NestFactory } from '@nestjs/core';
|
||||
|
||||
let port: number;
|
||||
|
||||
do {
|
||||
port = Math.round(Math.random() * 10000);
|
||||
} while (port < 1000);
|
||||
|
||||
@Injectable()
|
||||
class RpcOptionsProvider {
|
||||
getOptions(): TcpClientOptions {
|
||||
return {
|
||||
transport: Transport.TCP,
|
||||
options: {
|
||||
port,
|
||||
host: '0.0.0.0',
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@Controller()
|
||||
class RpcController {
|
||||
@MessagePattern({ cmd: 'sum' })
|
||||
sumPayload(@Payload() payload: number[]) {
|
||||
return payload.reduce((a, b) => a + b, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
ClientsModule.register([
|
||||
{
|
||||
name: 'RPC_CLIENT',
|
||||
transport: Transport.TCP,
|
||||
options: {
|
||||
port,
|
||||
host: '0.0.0.0',
|
||||
},
|
||||
},
|
||||
]),
|
||||
],
|
||||
controllers: [RpcController],
|
||||
providers: [RpcOptionsProvider],
|
||||
})
|
||||
class RpcModule {}
|
||||
|
||||
describe('RPC Async transport', () => {
|
||||
let app: INestMicroservice;
|
||||
let client: ClientTCP;
|
||||
|
||||
beforeEach(async () => {
|
||||
app = await NestFactory.createMicroservice<
|
||||
AsyncOptions<MicroserviceOptions>
|
||||
>(RpcModule, {
|
||||
logger: false,
|
||||
inject: [RpcOptionsProvider],
|
||||
useFactory: (optionsProvider: RpcOptionsProvider) =>
|
||||
optionsProvider.getOptions(),
|
||||
});
|
||||
|
||||
await app.listen();
|
||||
client = app.get('RPC_CLIENT', { strict: false });
|
||||
});
|
||||
|
||||
it(`/POST`, done => {
|
||||
let retData = 0;
|
||||
client.send({ cmd: 'sum' }, [1, 2, 3, 4, 5]).subscribe({
|
||||
next: val => (retData += val),
|
||||
error: done,
|
||||
complete: () => {
|
||||
expect(retData).to.eq(15);
|
||||
done();
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await app.close();
|
||||
});
|
||||
});
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Type } from '@nestjs/common';
|
||||
import { FactoryProvider, InjectionToken, Type } from '@nestjs/common';
|
||||
import { ConnectionOptions } from 'tls';
|
||||
import { Transport } from '../enums/transport.enum';
|
||||
import { ChannelOptions } from '../external/grpc-options.interface';
|
||||
@@ -28,6 +28,16 @@ export type MicroserviceOptions =
|
||||
| KafkaOptions
|
||||
| CustomStrategy;
|
||||
|
||||
export type AsyncMicroserviceOptions = {
|
||||
inject: InjectionToken[];
|
||||
useFactory: (...args: any[]) => MicroserviceOptions;
|
||||
};
|
||||
|
||||
export type AsyncOptions<T extends object> = {
|
||||
inject: InjectionToken[];
|
||||
useFactory: (...args: any[]) => T;
|
||||
};
|
||||
|
||||
/**
|
||||
* @publicApi
|
||||
*/
|
||||
|
||||
@@ -17,7 +17,10 @@ import { GraphInspector } from '@nestjs/core/inspector/graph-inspector';
|
||||
import { NestApplicationContext } from '@nestjs/core/nest-application-context';
|
||||
import { Transport } from './enums/transport.enum';
|
||||
import { CustomTransportStrategy } from './interfaces/custom-transport-strategy.interface';
|
||||
import { MicroserviceOptions } from './interfaces/microservice-configuration.interface';
|
||||
import {
|
||||
AsyncMicroserviceOptions,
|
||||
MicroserviceOptions,
|
||||
} from './interfaces/microservice-configuration.interface';
|
||||
import { MicroservicesModule } from './microservices-module';
|
||||
import { Server } from './server/server';
|
||||
import { ServerFactory } from './server/server-factory';
|
||||
@@ -43,7 +46,8 @@ export class NestMicroservice
|
||||
|
||||
constructor(
|
||||
container: NestContainer,
|
||||
config: NestMicroserviceOptions & MicroserviceOptions = {},
|
||||
config: NestMicroserviceOptions &
|
||||
(MicroserviceOptions | AsyncMicroserviceOptions) = {},
|
||||
private readonly graphInspector: GraphInspector,
|
||||
private readonly applicationConfig: ApplicationConfig,
|
||||
) {
|
||||
@@ -60,12 +64,22 @@ export class NestMicroservice
|
||||
this.selectContextModule();
|
||||
}
|
||||
|
||||
public createServer(config: NestMicroserviceOptions & MicroserviceOptions) {
|
||||
public createServer(
|
||||
config: NestMicroserviceOptions &
|
||||
(MicroserviceOptions | AsyncMicroserviceOptions),
|
||||
) {
|
||||
try {
|
||||
this.microserviceConfig = {
|
||||
transport: Transport.TCP,
|
||||
...config,
|
||||
} as any;
|
||||
if ('useFactory' in config) {
|
||||
const args = config.inject?.map(token =>
|
||||
this.get(token, { strict: false }),
|
||||
);
|
||||
this.microserviceConfig = config.useFactory(...args);
|
||||
} else {
|
||||
this.microserviceConfig = {
|
||||
transport: Transport.TCP,
|
||||
...config,
|
||||
} as any;
|
||||
}
|
||||
const { strategy } = config as any;
|
||||
this.server = strategy
|
||||
? strategy
|
||||
|
||||
Reference in New Issue
Block a user