Format request before send by ClientProxy
I use microservices and RabbitMQ as a transporter. My microservices communicate with each other, so one of them can send message to another one. I use the following way to send messages:
await this.client.send(SOME_COMMAND, obj).toPromise();
Now I need to format objects I send in all requests to any microservice in one place. For example add reqId, or serialize Map. Is it possible?
Solution 1:
1. Per controller solution. here for simplicity I removed the handler part:
@Controller()
export class AppController {
constructor(@Inject('MATH_SERVICE') private client: ClientProxy) {
let send = client.send.bind(client);
client.send = function (pattern, payload) {
return send(pattern, { payload, systemWideProp: ""})
}
}
sum() {
this.client.send(COMMAND, obj)
}
}
2. This could be as a provider
for injecting it on each controller you want using your rabbitmq
client service:
custom-client-proxy.ts
import { Inject, Injectable } from '@nestjs/common';
import { ClientProxy } from '@nestjs/microservices';
@Injectable()
export class CustomClientProxy {
constructor(@Inject('MATH_SERVICE') private client: ClientProxy) { }
send(pattern, payload) {
// payload and pattern manipulations such as:
// payload.say = "Hi";
// const scopePattern = { cmd: `${pattern.cmd}_dev` };
return this.client.send(pattern, payload)
}
}
app.module.ts
import { Module } from '@nestjs/common';
import { ClientsModule, Transport } from '@nestjs/microservices';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { CustomClientProxy } from './custom-client-proxy';
@Module({
imports: [ClientsModule.register([{
name: 'MATH_SERVICE',
transport: Transport.RMQ,
options: {
urls: ['amqp://localhost:5672'],
queue: 'math_queue'
},
}])],
controllers: [AppController],
providers: [AppService, CustomClientProxy],
exports: [CustomClientProxy] // export here for other modules of your app
})
export class AppModule { }
app.controller.ts also any controller you have imported under app's modules
@Controller()
export class AppController {
constructor(private client: CustomClientProxy) {}
sum() {
this.client.send(COMMAND, obj)
}
}
3. When you need to use this functionality for more than one queue
:
// custom-client-proxy.ts
@Injectable()
export class CustomClientProxy {
constructor() { }
send(client: ClientProxy, pattern, payload) {
// payload and pattern manipulations such as:
// payload.say = "Hi";
// const scopePattern = { cmd: `${pattern.cmd}_dev` };
return client.send(pattern, payload)
}
}
// app.module.ts
@Module({
imports: [ClientsModule.register([{
name: 'MATH_SERVICE',
transport: Transport.RMQ,
options: {
urls: ['amqp://localhost:5672'],
queue: 'math_queue'
},
},
{
name: 'MESSAGE_SERVICE',
transport: Transport.RMQ,
options: {
urls: ['amqp://localhost:5672'],
queue: 'message_queue',
},
}])],
controllers: [AppController],
providers: [AppService, CustomClientProxy],
exports: [CustomClientProxy]
})
export class AppModule { }
// app.controller.ts
@Controller()
export class AppController {
constructor(
@Inject('MATH_SERVICE') private mathClient: ClientProxy,
@Inject('MESSAGE_SERVICE') private messageClient: ClientProxy,
private client: CustomClientProxy) {}
sum(a) {
return this.client.sendTo(this.mathClient, pattern, payload);
}
}