How can nestjs reconnect to rabbitmq? - rabbitmq

I created a service for rabbitmq in nestjs.
and I use rabbitmq library, it's amqplib.
I would like to detect the colose event of rabbitmq.
When the rabbitqm connection is closed, a notification should be sent via the event emitter, but I want to catch it.
■ rabbtmq service
#Injectable()
export class RabbitmqService {
connection: Connection;
channel: Channel;
...
#OnEvent('close')
reconnect(msg: string) {
console.log('Message Received: ', msg)
}
}

Related

How to throttle a WebSocket client from sending too many messages in react-netty?

I am trying to build a group chat message using WebSocket using spring-webflux and rector-netty. I am new to reactor-netty framework and even after reading multiple articles posts I couldn't figure out if it is possible to throttle a client from sending too many messages in reactor-netty framework.
public class ServerWebSocketHandler implements WebSocketHandler {
Map<String, WebSocketSession> sessions = new HashMap<>();
ConcurrentLinkedQueue<String> messages = new ConcurrentLinkedQueue<>();
public ServerWebSocketHandler() {
// logic to start a thread which will drain all the messages in the queue to all the sessions periodically
}
#Override
public Mono<Void> handle(WebSocketSession session) {
System.out.println("Client connected: " + session);
sessions.put(session.getId(), session);
Flux<String> stringFlux = session.receive()
.map(WebSocketMessage::getPayloadAsText)
.map(String::toLowerCase)
.doOnNext(m -> messages.offer(m))
.doFinally(m -> System.out.printf("Client %s Disconnected due to %s\n", session, m));
return stringFlux.then();
}
}
ReactorNettyWebSocketSession is the implementation which is used in this case and it doesn't seem to expose any methods to have any control over the inbound/outbound, like marking the inbound as not readable or something. Is it possible to throttle/block a client from sending too many messages. If it is not possible, I am thinking that creating a bounded queue for each session and receive and then ignore/drop the incoming message in application layer.

Stomp + Rabbitmq to store offline messages

I am trying to create a one-to-one chat application using STOMP and RabbitMQ, but I want to store offline messages to queue and retrieve them once user is online. I am able to successfully create queue using convertandsendtouser and subscribe to get specific queues for a session. But as soon as the client is disconnected, if I try to send a message to same queue it does not get queued. How can I resolve this?
This is my Websocketconfig.
public void configureMessageBroker(MessageBrokerRegistry config) {
config.setApplicationDestinationPrefixes("/app");
config.enableStompBrokerRelay("/queue", "/topic", "/exchange", "/amq/queue")
.setRelayHost("localhost")
.setRelayPort(61613)
.setClientLogin("guest")
.setClientPasscode("guest");
}
public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
stompEndpointRegistry.addEndpoint("/gs-guide-websocket")
.addInterceptors(new HttpHandshakeInterceptor())
.withSockJS();
}
This is controller:
public void greeting(Principal principal, HelloMessage message) throws Exception {
Greeting greeting = new Greeting();
greeting.setContent("Hello from - " + message.getSenderName() + " message: -" + message.getName());
System.out.println(principal);
System.out.println("Message received" + message.getName());
SimpMessageHeaderAccessor ha = SimpMessageHeaderAccessor.create(SimpMessageType.MESSAGE);
ha.setSessionId(message.getToUser());
ha.setLeaveMutable(true);
messagingTemplate.convertAndSendToUser(ha.getSessionId(),"/queue/reply", greeting);
}
This is subscribe method:
stompClient.subscribe('/user/queue/reply',
function(greeting)
{
showGreeting(JSON.parse(greeting.body).content);
});
My queue get created with names as follows.
reply-userxvu304s5
I understand since there is a sessionId in the queue it persists messages only while there is some consumer connected. How can I change the name to persist messages in the queue if the user is offline also.

Java Spring Stomp AMQP

I have three project:
Javascript SockJS STOMP client
Spring-boot STOMP endpoint and AMQP
Spring-boot AMQP (RabbitListener) client for testing
I am using RabbitMQ message broker (+Stomp plugin) and configured amqp and stomp endpoint normally..When I send message to queue with RabbitTemplate and third project (spring-boot amqp client for testing) normally subscribed this message , everything works fine !! But Javascript STOMP client didn't received this message..
P.S. When I send message with SimpMessagingTemplate , JS client receives message fine !
Javascript SockJS STOMP Client
var socket = new SockJS('http://localhost:8090/hello');
stompClient = Stomp.over(socket);
stompClient.connect('guest','guest', function(frame) {
setConnected(true);
console.log('Connected: ' + frame);
stompClient.subscribe('/topic/testqueue', function(greeting){
showGreeting(JSON.parse(greeting.body).content);
});
});
spring-boot STOMP endpoint and AMQP
#Controller
public class SampleController {
Logger logger = Logger.getLogger(SampleController.class);
#Autowired
private RabbitTemplate rabbitTemplate;
private SimpMessagingTemplate messagingTemplate;
#Autowired
public SampleController(SimpMessagingTemplate messagingTemplate) {
this.messagingTemplate = messagingTemplate;
}
#GetMapping("/emit/{message}")
#ResponseBody
String queue1(#PathVariable("message") String message) throws Exception {
logger.info("Emit to testqueue");
rabbitTemplate.convertAndSend("/topic/testqueue", new Greeting("Salam olsun " + message));
Thread.sleep(60000); // simulated delay
return "Emit to testqueue";
}
}
spring-boot amqp client for testing
#Component
public class RabbitMqListener {
Logger logger = Logger.getLogger(RabbitMqListener.class);
#RabbitListener(queues = "/topic/testqueue")
public void processQueue1(String message) {
logger.info("Received from queue : " + message);
}
}
How I can mix amqp and stomp protocols in RabbitMQ ? I want to send message from another project with amqp protocol (RabbitTemplate) and receive this message from JS STOMP client (SockJS) .. Thanks.
I was changed rabbitTemplate.convertAndSend("/topic/testqueue", ...) to rabbitTemplate.convertAndSend("amq.topic","testqueue" ...) and everythink works fine ))) Especially thanks to Artem Bilan for support. Good Luck

RabbitMQ C# message based listener

I want to webapplication and in the backend I open a new thread and start a listener.What I want ,open connection one time and rabbitmq listener start and when new message is coming ,it is processed in background.
What is the best approach for this?
Why do you need to listen events in web application?
Instead of it, write a windows service using topshelf and masstransit as a rabbitmq client.
You can connect to rabbitmq and register listener consumers in Program.cs as below:
IBusControl busControl = Bus.Factory.CreateUsingRabbitMq(cfg =>
{
IRabbitMqHost host = cfg.Host(new Uri(RabbitMQConstants.RabbitMQUri),
hst =>
{
hst.Username(RabbitMQConstants.RabbitMQUserName);
hst.Password(RabbitMQConstants.RabbitMQPassword);
});
cfg.ReceiveEndpoint(host,
RabbitMQConstants.YourQueueName,
endPointConfigurator => { endPointConfigurator.Consumer<SomeConsumer>(); });
});
And start bus configurator :
busControl.Start();
Example consumer:
public class SomeConsumer :
IConsumer<YourMessageClass>
{
public async Task Consume(ConsumeContext<YourMessageClass> context)
{
await Console.Out.WriteLineAsync($"Message consumed: {context.Message.YourValue}");
}
}
For more information and example take a look at offical masstransit documentation : http://masstransit-project.com/MassTransit/usage/message-consumers.html

How to Reinitialize a DefaultConsumer's Channel on Shutdown

I am using a RabbitMQ DefaultConsumer
public void init () {
DefaultConsumer dc = new DefaultConsumer(channel);
dc.addShutdownListener(this);
}
handleShutdownSignal() {
//TODO: Recreate channel associated with this consumer
}
Once there is an error with the channel, and a shutdownsignal is sent, how can I reinitialize the channel since the consumer is already dependent on the previous channel it was using ?
You will need to re establish the connection, create a channel and then create a new consumer. If the connection is still ok you may be able to use that to get a new channel.