I am building browser application with real-time updates.
Application allows to read and edit spreadsheet together with other people online.
However, some people have poor Internet connection and disconnects may occur.
I want application to be able to update to the latest data after Internet reconnection.
Currently Pusher and application work so:
Pusher connects to server and receives events.
Other people make changes in spreadsheet.
Application receives these changes from Pusher and is able to reflect them on spreadsheet.
At some moment Internet disappears.
Pusher detects this and automatically tries to reconnect.
Other people make changes in spreadsheet.
Application can't receive these changes because there is not Internet connection.
After some time, for example 5 minutes, Internet connection seems to be ok.
Now Pusher successfully reconnects to server.
However, Pusher doesn't receives events from period when there was no Internet connection (list item #6).
Other people make changes.
Pusher receives events and application is able to handle them.
So my problem is: Pusher doesn't receive events after automatic reconnect which were triggered by other people during Internet disconnection.
I am using default Pusher configuration, private channel, latest stable version and don't do any magic.
Pusher does not currently provide this functionality. To implement this yourself you would have to send a numeric ID with each message that increases in value. You would also need to store a cache of all sent messages in a database. Clients can keep track of the last ID they received. After disconnecting and reconnecting, they can send a request to your server asking for all messages greater than the last message ID they received. Your server should respond with messages matching that query in your database.
Related
I’m bulilding a web app that requires communication between clients. For this I’m using socket.io. Some data however has to be updated regularly in the database.
Some of them not that often (preferences, on button click) others in every second for example a timer value. This can not be calculated because the timer can be paused.
Right now whenever a client emits an event, it also makes a request to the backend to updated the database. I was wondering if it would be a good idea to have the socket.io server update the database so the clients would only have to take care of the socket communication? It seems to me that having the browser do a request to the backend is a bit resource heavy and takes out a bit from the advantages of the socket based communication
Edit: the back end of the app and the socket server are two different servers but physically they are on the same machine so their communication could be faster
the main point of using socket.io is that it allows you to push data to clients and clients do not need to check your server constantly to get the last changes, and providing a low-overhead communication channel between the server and the client.
you can call an API and also emit data and many other things on user click in your application.
it is a good idea to have the socket.io server update the database and you can also authorize each socket, save client sockets information and ...
I'm working on making an iOS app that does a few things, some of which would benefit from real-time data streams (like chat)
For right now I have a few handlers on my server, one of them gets all the threads a user has access to, another can get messages (offset, all, time-ranged, etc.) for a thread. When a user sends a message to a thread, I get all the listeners for the thread and send them a push notification. This works, but I was reading through the APNS docs and it says "dont do more than 3/hr" and I'm definitely doing more than 3/hr.
So I'm thinking I move to websockets. I know how to synchronize pub/subs across machines via redis so I'm not worried about that, I'm more stuck on the following:
If I start to bring websockets into the project, should I just pump all the information App <-> Server through the websocket? Create a thread -> Don't POST, just send a message along the socket. Get a message -> Don't poll or send notification, just send a message along the socket. Literally anything -> Don't make a request, just send a message along the socket.
Right now I'm leaning towards loading initial state and bulk data via normal HTTP URLs (eg: Create a thread, load the last 20 messages for thread XYZ), but for data that needs to be pushed and received in real time (eg: Chat Message send/recv) do that via a websocket.
I am setting up an MQTT/Websockets server, my client is an flutter app, which connects to the broker on main screen, and in other screens it sends and receive messages from the broker. My understanding of keepAlive is how often the client and server should share ping/pong, so they make sure the connection is still alive. being said, if my flutter app, connects to the broker in main screen, of 3600/1 hour keepAlive, and suppose to share and receive messages on other screens, if i disconnect the client from the internet for 2 minutes, and reconnect after that, it will not send/receive messages, maybe my understanding of keepAlive is not correct. Well, How would i structure my app/server to reconnect automatically to the internet as soon as internet connection is back and up again.
I have also tried On.Disconnect method, which i noticed it will never get called, and the app even though still thinks its connected to the broker.
I mentioned websockets, on the tags as i could do mqtt over websockets.
I see that no-one else has responded, so I'll try (however I'm new to this also).
Also, have you looked at the Flutter connectivity package?
From my reading of the Mqtt specification, it seems the Mqtt client ** should** disconnect the TCP/IP connection if it doesn't receive a PINGRESP to its PINGREQ in the keep alive period (ie it's not required to disconnect).
My Flutter + Mqtt app checks the connection state, and reconnects if needed, every time it sends a message. I haven't needed to check for internet dropouts, but I have noticed the connection is lost on some application state changes. The main app widget. is notified of these using didChangeAppLifecycleState() and sends a dummy message if needed.
So this doesn't answer exactly what you asked, but I hope it's useful anyway.
I have an application in which clients use websockets to connect to a server which is running Spring Boot Tomcat.
My question is if there is a way for the server to detect a client disconnect due to a network loss.
Thanks.
if you are using stomp , check SessionDisconnectEvent.
For raw Websocket connections, you can use :
WebSocketHandler-->afterConnectionClosed
I have searched before for this and the solution I was able to find was to implement a ping-pong mechanism between the server and the clients.
For example, each few seconds send a dummy message to the client on a specific topic and receive back another dummy reply, if you didn't get a reply for a configured period you can consider the client disconnected.
As mentioned here,
STOMP and Spring also allow us to set up topics, where every
subscriber will receive the same message. This is going to be very
useful for tracking active users. In the UI, each user subscribes to a
topic that reports back which users are active, and in our example
that topic will produce a message every 2 seconds. The client will
reply to every message containing a list of users with its own
heartbeat, which then updates the message being sent to other clients.
If a client hasn't checked in for more than 5 seconds (i.e. missed two
heartbeats), we consider them offline. This gives us near real time
resolution of users being available to chat. Users will appear in a
box on the left hand side of the screen, clicking on a name will pull
up a chat window for them, and names with an envelope next to them
have new messages.
I built a small server (golang) to grab messages from a RabbitMQ and deliver them to connected browsers via a Websocket.
It works quite well, though has one caveat: the messages are acknowledged when delivered to the browser via the websocket. For most messages that is ok but some messages might be very important. If the user's browser received those but the user didn't SEE the message, it would be lost if the browser was closed or reloaded.
Is there a way to ack a message at a later time based on its message id (from the Delivery struct)?
The use case would be that some messages are acked when the user acknowledges them explicitly and at that point the message id is sent back to the tool to be acknowledged with RabbitMQ.
Even if you can do this, it's bad design.
What happens to the message if the user doesn't see it? Does your web server infinitely hang on to it? Does it "nack" the message back to the queue?
Neither of these options are good.
Hang on to every message, and RabbitMQ will start having issues with thousands of unacknowledged messages from a lot of users. Nack the message back to the queue and you'll thrash the message round in circles, spiking CPU resources on the web server and the RMQ server, as well as network traffic between the two.
The better solution to this problem is to store the message in a database, after pulling it out of RabbitMQ. When it gets sent to / viewed by the browser, update the database to reflect that.
From a yet-unpublished article I've written:
Store the message in a database.
Add a field to the database record that says who this message belongs
to. When the user reconnects later, query the database for any
messages that this user needs to see and send them along at that time.
The full process started above, then becomes this:
User's browser connects to SignalR/Socket.io/Pusher/websockets on web
server
Web server checks a queue for updates that happen during a long
running process
When a message for a logged in user comes in
If the
user is logged in, broadcast the message through the websocket to the
user
If the user is not logged in, store the message in a database
When the user logs in again, query the database and send all waiting
messages
It's what you would have done before the idea of a message
queue came in to play, right? It should be what you would do now that
you have a message queue, as well.