Socket.io isnt updating its connection when using NestMicroservice

71 views Asked by At

hello, so when i called the @EventPattern from NestMicroservice i also want to emit an event via socket.io: with this.websocketService.emitToRoom(...)

import { Controller } from '@nestjs/common';
import { EventPattern } from '@nestjs/microservices';
import WebsocketEvent from 'src/common/interfaces/websocket/WebsocketEvent';
import { WebsocketRoom } from 'src/common/interfaces/websocket/WebsocketRoom';
import { FCMTokenService } from 'src/modules/fcm-token/fcm.token.service';
import { NotificationService } from 'src/modules/notification/notification.service';
import { WebsocketService } from 'src/modules/websocket/websocket.service';

@Controller()
export class FCMTokenMicroserviceController {
  constructor(
    private readonly fcmTokenService: FCMTokenService,
    private readonly notificationService: NotificationService,
    private readonly websocketService: WebsocketService
  ) {}

  @EventPattern({ cmd: 'sendNotificationByUserIds', service: 'fcm-token' })
  async sendNotificationByUserId(
    messages: {
      userId: number,
      notification: INotificationPayload,
      data?: Record<string, any>
  }[]
  ): Promise<void> {
    for (const message of messages) {
      const notification = await this.notificationService.save({
        payload: message.data,
        notification: message.notification,
        userId: message.userId
      });
      
      // This socket still doesnt have any client connected and idk why
      this.websocketService.emitToRoom(WebsocketRoom.notification, WebsocketEvent.notification(message.userId), notification);

      await this.fcmTokenService.sendNotificationByUserIds({
        userIds: [message.userId],
        notification: message.notification,
        data: message.data
      });
    }
  }
}

But the problem is the socket still have no client connected. So i assume the socket was calling the old socket which still has 0 client connected to it because when i using other module to test the socket (such as graphql) the socket get updated with 1 client connected, it works as expected.

so what did i do wrong here?

websocket.service.ts

import { Injectable } from '@nestjs/common';
import { WebsocketGateway } from './websocket.gateway';
import { WebsocketRoom } from 'src/common/interfaces/websocket/WebsocketRoom';

@Injectable()
export class WebsocketService {
  constructor(
    private readonly websocketGateway: WebsocketGateway
  ) {}
  
  async emitToRoom(room: WebsocketRoom, event: string, data: any) {
    // This still have no client when called via microservice
    console.log('\n', await this.websocketGateway.server.in(room).fetchSockets());
    console.log('\n', this.websocketGateway.server.listenerCount(event), this.websocketGateway.server.listeners(event));
    return this.websocketGateway.server.to(room).emit(event, data);
  }
}

websocket.gateway.ts

import { UseGuards } from "@nestjs/common";
import { ConnectedSocket, MessageBody, SubscribeMessage, WebSocketGateway, WebSocketServer } from "@nestjs/websockets";
import { Server, Socket } from "socket.io";
import { WSGuard } from "src/common/guard/WSGuard";

@WebSocketGateway({
  cors: true,
  path: '/ws',
})
export class WebsocketGateway {
  @WebSocketServer() 
  server: Server;

  @UseGuards(WSGuard)
  @SubscribeMessage('joinRooms')
  joinRoom(
    @ConnectedSocket() client: Socket,
    @MessageBody() body: JoinRooms
  ) {
    client.join(body.rooms);
  }
}

and yes the client is successfully connected to the both socket and room.

1

There are 1 answers

0
Melvin Jovano On

My workaround is to make a global variable somewhere, then use it in the WebsocketService. It seems that the NestMicroservice didnt update the websocket server because its in then different server (i have graphql and microservice both with different ports), so the server inside the NestMicroservice didnt get updated. Still if theres a cleaner workaround or something i missed i'd appreciate it...

ServerWS.ts

import { Server } from "socket.io";

export default {
    server: new Server()
};