Search code examples
websocketnestjsmicroservices

Nestjs Hybrid application websocket + microservice


I have a problem with Nestjs, with starting a microservice that listens to a messagebroker, while simultaneously starting a websocket server with which we can communicate with front-end clients.

So I am aware of hybrid nest applications, where the websocket gateway can be injected into the microservice. However I get errors about Nest not being able to resolve the Gateway import. I configured the microservice in a ResultsModule, the websocket in UsersModule.

The error I get is:

ERROR [ExceptionHandler] Nest can't resolve dependencies of the ResultsController (ResultsService, ?). Please make sure that the argument UsersGateway at index [1] is available in the ResultsModule context.

These are the relevant pieces of code:

main.js

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.connectMicroservice<MicroserviceOptions>({
    transport: Transport.RMQ,
    options: {
      urls: [
        `amqp://${config.rabbitmq.username}:${config.rabbitmq.password}@${config.rabbitmq.host}:${config.rabbitmq.port}`,
      ],
      queue: config.rabbitmq.channelListen,
      noAck: false,
      queueOptions: {
        durable: false,
      },
    },
  });

  await app.startAllMicroservices();
  await app.listen(82);
}
bootstrap();

app.module.ts

@Module({
  imports: [UsersModule, ResultsModule],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

results.module.ts

@Module({
  imports: [UsersModule],
  controllers: [ResultsController],
  providers: [ResultsService],
})
export class ResultsModule {}

users.module.ts

@Module({
  providers: [UsersGateway, UsersService],
})
export class UsersModule {}

users.gateway.ts

import {
  WebSocketGateway,
  SubscribeMessage,
  MessageBody,
  OnGatewayInit,
  OnGatewayConnection,
  OnGatewayDisconnect,
  WebSocketServer,
  ConnectedSocket,
} from '@nestjs/websockets';
import { Socket, Server } from 'socket.io';
import { UsersService } from './users.service';
import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto';

@WebSocketGateway(82)
export class UsersGateway
  implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect
{
  constructor(private readonly usersService: UsersService) {}
  @WebSocketServer() server: Server;
  afterInit(server: Server) {
    console.log('init');
  }

  handleDisconnect(client: Socket) {
    console.log(`Client disconnected: ${client.id}`);
  }

  handleConnection(client: Socket, ...args: any[]) {
    console.log(client.id);
  }

  @SubscribeMessage('resource')
  create(
    @MessageBody() createUserDto: CreateUserDto,
    @ConnectedSocket() client: Socket,
  ) {
    console.log(client.id);
    console.log(createUserDto.resourceId)
  }
}

I tried to move around the imports, not wrapping the gateway in a module. Tried moving the results module out of the app.module. Which removes the error, however then I do not understand where to let nestjs know to use the resultsmodule for the microservice.

------------------------ANSWER-------------------------------------

Alright, we fixed it with the help of @yomateo , we were missing the export of the websocket gateway in the module. Thanks for the help!


Solution

  • You're close (you have it backwards).

    Have your UsersGateway or UsersService call the ResultsService.