Affects: spring-messaging:5.2.1-RELEASE
Problem: Wrong broadcasting behavior.
I'm using spring-messaging to deal with websockets and STOMP as subprotocol.
When some clients subscrib to specific topic my application starts broadcasting all sessions with:
SimpMessagingTemplate.convertAndSend(String destination, Object payload); method.
As I can see in SimpleBrokerMessageHandler logs all subscribers get their messages.
But then spring triggers HeartbeatTask (inside SimpleBrokerMessageHandler) and sends DISCONNECT_ACK frame to the client and removes session (SessionInfo) from cache.
So as a result we can not send messages to the user anymore.
This happens because I use convertAndSend instead of convertAndSendToUser so
updateSessionReadTime(sessionId); method is ignored (when using convertAndSend no sessionId is sent).
I suppose that we should update lastReadTime in sendMessageToSubscribers() as it happens with lastWriteTime or rewrite updateSessionReadTime() that will handle sessions according to destinations.
Comment From: rstoyanchev
The lastReadTime is used to track missed heartbeats from the WebSocket client, which would indicate something wrong with the connection.
The lastWriteTime is used to track the last time the server wrote a message, so it can send a heartbeat otherwise.
All looks good to me. Messages broadcast from the server do not affect the lastReadTime and sendMessageToSubscribers updates the lastWriteTime.
Comment From: Maxim-Gadalov
Thank you for your feedback. As far as I understand client sends heartbeat message if no message received from server for specified time.
So if client only subscribes to the certain topic(s) and keeps listening server messages - no heartbeat messages will be sent from client to server.
Since broadcasting multiple sessions do not track lastReadTime - server decides that client is dead and removes session from cache and sends DISCONNECT_ACK frame to the client.
This issue will not appear if we use convertAndSendToUser() method, because before sending message to the client lastReadTime will be updated.
In other words server will not send heartbeat message because lastWriteTime updates every time broadcast happens and lastReadTime will not be updated because broadcast message has no sessionId. As a result SimpleBrokerMessageHandler removes session from cache and can not route messages to the client anymore.
Comment From: rstoyanchev
As far as I understand client sends heartbeat message if no message received from server for specified time.
No, not how it works. Client is supposed to send messages regularly, and if there aren't any there should be heartbeat. The point is that both sides should never go quiet.
Comment From: Maxim-Gadalov
Thank you for your explanation. I misunderstood how heartbeat should works. I suppose, we should close this issue.