Architecture for real-time application, avoiding duplicate messages for queues with no active consumers

backendfront-endmessage-queuereal timesynchronization

I am designing the architecture of an application which has your typical backend and frontend components. The frontend application must be semi real-time. For this requirement, the backend is pushing messages on a queue and the frontend is consuming that queue. Most likely, I will be using RabbitMQ for this. Let me explain.

When the user is logged in into the frontend application, a session is created in the backend. As long as this session is valid, the frontend application is allowed to operate. Typically, after the log-in, the frontend initially loads all data from a REST API (with his session as authentication credentials) and all subsequent updates will be received via the message queue.

In my current design, each frontend session has its own queue. So whenever something changes in the backend, a message is sent to all relevant session queues. As said, the frontend is consuming this queue.

The problem is when the frontend is disconnected from the queue. For example, when the user hibernates his laptop at the end of his working day. From then on, messages starts piling up. The real problem is here that the queue becomes populated with duplicated messages. The longer the client is disconnected from the queue, the bigger this problem becomes.

Small side-note, with duplicate messages I actually mean semantically identical messages. Take a stock exchange application for example. Two price of stock xyz has been changed messages are semantically identical. They come from a different event/transaction, but define the same change. So, the previous message has become obsolete by the new one. See comments for more detail.

I am looking for an architecture to solve this. Let me go over my thoughts:

  • Instead of having a session queue, I could have created a session exchange. After the log-in, a dedicated, auto-delete, private queue could be made which is bound to that exchange. After the disconnect/timeout, this queue will be deleted by the broker. Then, when the frontend application comes back, a new queue will be made. In other words, the frontend application returns with an empty queue.

    • But, this forces the client to refresh all data after a reconnect. Everything could have been changed.
    • I would like to keep the client as dumb/simple as possible.
    • Therefore, I believe this is not an optimal solution.
  • So, it would make sense to solve this in the backend. In other words, I need a way to prevent duplicate messages on the session queues. If a certain message is already in the queue, I will not queue the same message again.

    • What are my options here? How do I find out that a certain message is already in the queue? I perfectly understand that this is not directly supported by AMQP. So, to implement this on my own, I believe this means means I should be able to keep track on message delivery and ideally also on message acknowledgements. Is this possible?
    • Another route could be to make us of the TTL, dead-letter, … functionalities of the (Rabit)MQ broker. However, I could not come up with something that really works.

My question boils down to this: how do I get the client up to date after a disconnect?

Any ideas or insights are very welcome.

Best Answer

I am not sure to see the values of the queues here, a direct bidrectionnal communication would be better, and would solve your current problem, when the user come back from hibernating his computers, he has to refresh fully his page to trigger back the bidrectionnal communication.

If you use Web application, look for STOMP/Web Socket, if you don't, you can still use STOMP and Web Socket, but a simple TCP Connection could do the work too.

Note that they're libraries to provide very reliable TCP Connection with auto-reconnect and so on to handle network troubles don't go the way to code that again, such things are really a pain to develop and tests properly.

Others way :

  • Instead of delivering the messages one by one to the client, deliver everything when they're more than one, translate them to an Set (collection of unique objects) of actions to do and perform all the Actions.
  • Why the session of the user just don't expires after like 30mn of inactivity ? When it expires clean the queue.
  • RabbitMQ does not implements JMS Spec, so it may not have an equivalent of JMS Topic with durable subscriptions, which seems to fit better than your system.
Related Topic