Basics

It is unbelievably simple to transform Nest application into Nest microservice.

Take a look - this is how you create web application:

const app = NestFactory.create(ApplicationModule);
app.listen(3000, () => console.log('Application is listening on port 3000'));

Now, switch it to a microservice:

const app = NestFactory.createMicroservice(ApplicationModule, { port: 3000 });
app.listen(() => console.log('Microservice is listening on port 3000'));

It's everything!

Communication via TCP

By default Nest microservice is listening for messages via TCP protocol. It means that right now e.g. @Get() will not be useful, because it is mapping HTTP requests. So, how microservice will recognize messages? Just by patterns.

What is pattern? It is nothing special. It could be an object, string or even number (but it is not a good idea).

Let's create MathController:

import { MessagePattern } from '@nestjs/microservices';

@Controller()
export class MathController {
    @MessagePattern({ cmd: 'add' })
    public add(data: number[]): Observable<number> {
        const numbers = data || [];
        return Observable.of(numbers.reduce((a, b) => a + b));
    }
}

As you might seen - if you want to create message handler, you have to decorate it wih @MessagePattern(pattern). In this example, I chose { cmd: 'add' } as a pattern.

The handler method receives single argument - data, which is a variable with data sent from another microservice (or just web application).

Also, the handler returns Observable from Rxjs package, so it's possible to return multiple values. IMPORTANT! You have to complete Observable if you want to terminate the data stream.

Client

You already know how to listen for messages. Now, let's check how to send them from another microservice or web application.

Before you can start, Nest has to know, where you're exactly going to send messages. It's easy - you only have to create @Client object.

import { Controller } from '@nestjs/common';
import { Client, ClientProxy, Transport } from '@nestjs/microservices';

@Controller()
export class ClientController {
    @Client({ transport: Transport.TCP, port: 5667 })
    client: ClientProxy;
}

@Client() decorator receives object as a parameter. This object can have 3 properties:

  • transport - with this you can decide which method you're going to use - TCP or Redis (TCP by default),
  • url - only for Redis purposes (default - redis://localhost:6379),
  • port (default 3000).

Use client

Let's create custom endpoint to test our communication.

import { Controller, Get } from '@nestjs/common';
import { Client, ClientProxy, Transport } from '@nestjs/microservices';

@Controller()
export class ClientController {
    @Client({ transport: Transport.TCP, port: 5667 })
    client: ClientProxy;

    @Get('client')
    public sendMessage(@Res() res: Response) {
        const pattern = { cmd: 'add' };
        const data = [ 1, 2, 3, 4, 5 ];

        this.client.send(pattern, data)
            .catch((err) => Observable.empty())
            .subscribe((result) => res.status(200).json({ result }));
    }
}

As you might seen, in order to send message you have to use send method, which receives message pattern and data as an arguments. This method returns an Observable.

It is very important feature, because reactive Observables provide set of amazing operators to deal with, e.g. combine, zip, retryWhen, timeout and more...

Of course, if you want to use Promises instead of Observables, you could simply use toPromise() method.

That's all.

Now, when someone will make /test request (GET), that's how response should looks like (if both microservice and web app are available):

{
  "result": 15
}

results matching ""

    No results matching ""