Unable to send message in task scheduler, Nestjs microservices

70 views Asked by At

I use NestJs with modules Microservices and Task Schedule to send data from Client to Service (transport: TCP). If I use PostMan to test call API, the service receives data, but the run task schedule does not.

1. Project Service runs on port 3000

File main.ts

async function bootstrap() {
  const app = await NestFactory.createMicroservice<MicroserviceOptions>(
    AppModule,
    {
      transport: Transport.TCP,
      options: {
        port: 3000,
      },
    },
  );
  await app.listen();
}
bootstrap();

File app.controller.ts

@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}

@MessagePattern({ cmd: 'get_book' })
getBook(bookID: string): BookDTO {
console.log('getBook', bookID);
return this.appService.getBookByID(bookID);
}
}

2. Project Client runs on port 3001 and connect TCP to Project Service on port 3000

File main.ts

async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(3001);
}
bootstrap();

File app.module.ts

@Module({
  imports: [ConfigModule.forRoot(), ScheduleModule.forRoot()],
  controllers: [AppController],
  providers: [
    {
      provide: 'BOOKS_SERVICE',
      inject: [ConfigService],
      useFactory: (configService: ConfigService) => {
        return ClientProxyFactory.create({
          transport: Transport.TCP,
          options: {
            host: 'localhost',
            port: 3000,
          },
        });
      },
    },
  ],
})
export class AppModule {}

File app.controller.ts

@Controller('booksstore')
export class AppController {
constructor(@Inject('BOOKS_SERVICE') private client: ClientProxy) {}

async onApplicationBootstrap() {
await this.client.connect();
}

@Get(':id')
getBookByID(@Param('id') id) {
return this.client.send({ cmd: 'get_book' }, id);  // Service receives data (test call API)
}

@Cron(CronExpression.EVERY_5_SECONDS)
scheduleTest() {
console.log('scheduleTest', new Date());
return this.client.send({ cmd: 'get_book' }, 123);  // Service doesn't receive data
}
}

Where is the problem? The function task schedule still runs every 5 seconds, but the Client can not send data to Service (Port 3000).

1

There are 1 answers

0
Avius On

ClientProxy.send() returns an Observable. In order for an Observable to start, there must be someone subscribed to it. When a route handler (e.g. @Get(:id)) returns an Observable, NestJS automatically subscribes to it and sends the first emitted value as a response to the client (Postman).

However, a method decorated with @Cron() is not a route handler, and if it returns an Observable, NestJS does not automatically subscribe to it, and thus the Observable action is never triggered.

The fix is simple - you could invoke .subscribe() on the value returned from .send():

@Cron(CronExpression.EVERY_5_SECONDS)
scheduleTest() {
    console.log("scheduleTest", new Date());
    this.client.send({ cmd: "get_book" }, "12345").subscribe();
}

Up to you what you wish to do about possible error handling.