1

I have a chat application that is build using Spring Websokcets (with STOMP) and the message broker I have used is RabbitMQ.

First I will try to explain the flow little bit. In my application same user can be connected to the websocket server from different devices. To keep the things simple, each user will be subscriber to /topic/{userId}. So when somebody sends a message to user 123, he will be able to see that message in all his devices he is connected from, because I am just sending that message to the destination /topic/{userId}.

My problem is before sending a message to a particular topic, I want to check how many users are connected this topic at this point(this number specifies the number of devices the user logged in from). If this number is 0, I want to send this message to a separate queue.

I have checked this question they look very similar to my problem. But I believe that my problem is even simpler. I just want to find out the number of users, I don't need any information about them.

In the question I mentioned above Brian Clozel mentioned that it's possible to get the information about subscription from RabbitMQ REST API, I have searched about how to do this.

If I want to know the number of users that are subscribed to a topic /topic/123, how do I find it out using RabbitMQ API?

I have also checked this this ticket, and it seems there is added support for this use-case but as far as I understood, it will work only with SimpleMessageBroker. Can somebody clarify If I am correct.

I will be able do this using Application Context Events but this would work only for a single server. In a distributed system this will not work. So I thought getting that information from RabbiMQ is the right way of doing it.

UPDATE

Let me explain more clearly what I am trying to do. Say I am a user with userid 123 and If I am logged in to the site from three devices Laptop1,Laptop2 and Mobile1. Initially all of them will be subscribed to /topic/123 (123 is UserId here).

Basically I want to solve two problems:

1) I don't want to keep the websocket connection open even if the user is inactive, so I close the websocket connection after a certain time of inactivity. In reality even If the mobile is inactive, it should be able to get the notifications, So my app will be pinging a notification server to get the notification(not just messages, any kind of notifications). Now say there is an incoming message for 123, if I know that there are no consumers connected to /topic/123 and if the user 123 has our app installed(somehow I will know this information) I want to send push this message to the notification server so that the mobile app will be able to get the message even if the websocket connection is closed.

2) second problem is, say all three connections (Laptop1,Laptop2,Mobile1) are active and there are incoming messages, I want to show notification in only one of the active client (as Gmail or Facebook does). If there is an incoming message to a client and if it knows that there are more than one devices(I can send this information from server) subscribed to /topic/123, at the client side I can decide whether to show the pop-up or not.

Community
  • 1
  • 1
Karthik
  • 4,950
  • 6
  • 35
  • 65
  • what are you trying to accomplish, here? the idea of knowing how many consumers there are for a particular topic is not something you should need to do, i think... there is probably a better design, but i would need to know what your intention is (more than jsut 'send to a different queue' - whey do you want to send it to a different queue?) – Derick Bailey Jul 29 '15 at 16:06
  • @DerickBailey I edited the question and tried to explain the problems I am trying to solve. If you think there are better ways to solve those problem, please suggest. – Karthik Jul 29 '15 at 16:29
  • I believe your program flow logic has become entangled in your message routing logic. If you think about the behavior required, and focus less on the message flow or what you think is possible with your setup, it may help guide you to the proper design. **It is not proper for a publisher to know or care about the number of subscribers.** – theMayer Jul 30 '15 at 15:04
  • @theMayer normally that's the case, but for this specific use case,I thought the only way of doing in either intercepting the application context events or querying RabbitMQ(somehow). If you feel there is a better way, please suggest. – Karthik Jul 30 '15 at 15:17
  • @theMayer before going to push to a topic, at least I should know whether there are any subscribers listening to the queue or right? – Karthik Jul 30 '15 at 15:22
  • I don't have time at the moment to write up a complete response, I apologize. Give me a few hours. – theMayer Jul 31 '15 at 03:58
  • @theMayer It will be really helpful if you can spend some time and put up your answer. Thank you :) – Karthik Aug 02 '15 at 19:46

1 Answers1

0

Given the features that you want in your application, you are going to need something in front of RabbitMQ - a web server or other application server that can host your websockets, and provide the logic required.

RabbitMQ will deliver messages to queues, based on routing keys. Any consumer connected to the queue has a chance of receiving the message. If there are multiple consumers connected to a queue, RabbitMQ will round-robin the messages to the consumers. There is no guarantee that a specific consumer will receive a specific message, unless you only have 1 consumer on a given queue.

The need to only send a notification to a single connected device implies an order of precedence for a list of devices - which one is more important and should receive the notification. The order of precedence appears to be dynamic based on your requirements... how active the user is on the given device will change whether or not that device should receive the notification or not.

This type of logic is not really possible in RabbitMQ directly.

I would recommend building a web server that sits in front of RabbitMQ and have all of your devices connect to that web server. Use the web server to facilitate the web sockets and have the web server keep track of which device is most active for a given user. The web server can use that knowledge to determine which device receives the notification.

Derick Bailey
  • 72,004
  • 22
  • 206
  • 219
  • I have a websocket server in front of `RabbitMQ`, that is what I meant by `Spring Websokcets (with STOMP)`. To implement this logic in websocket server, I need to use `ApplicationContextEvents` and it will not efficiently in a clustered environment. That is why I wanted to know if there is any way to find the number of consumers subscribed to a particular queue. If you check the answer here, http://stackoverflow.com/questions/24795340/how-to-find-all-users-subscribed-to-a-topic-in-spring-websockets , he says it is possible, but i did not find any source in internet. – Karthik Jul 30 '15 at 15:02
  • and also `Any consumer connected to the queue has a chance of receiving the message. If there are multiple consumers connected to a queue, RabbitMQ will round-robin the messages to the consumers` is not exactly correct I guess when RabbitMQ is acting as a message broker for websockets. All the subscribers will get the message. If I create a group chat application, this is how it should work and this is how it works. – Karthik Jul 30 '15 at 15:12