At the end of the summer, we
added support for messaging to our Voximplant cloud. Now, with the help of it and the placer SDK for different platforms, you can make your own mobile or web messengers: voice calls in any combination between telephone networks and SDK - is, video calls between SDK - is, messedging - is. And text messages have a key difference from voice and video calls: their content should remain. Voximplant can record voice and video calls on the cloud side and give a URL with the resulting file, but this is a “slow” story for CRM, order management systems and call centers. A message is a quick story. The user is very upset when clicking on the “old” chat in Skype causes the hang of a mobile or web application that is trying to download at least some history from the loaded servers on an unstable 3G. In our SDK, we have provided several mechanisms for the fastest possible work with the history of messages about which under the cat.
What is the problem?
A new messenger user starts with a single
Messenger object, which gives access to the API and allows you to receive events. Communication between users begins when one of them creates a
Conversation object (“conversation” or “chat” for two or more) and they begin to exchange messages using the method of this object
sendMessage . Clients will learn about the events with the help of events. For example, if user “A” wants to send a message to user “B” for the first time, then he creates a conversation for two, after which both of them come to the Event
CreateConversation , through which user “B” finds out that they want to communicate with him. Also, events signal new messages, joining conversations and leaving users, changing admin status or that the user types the text.
All this idyll lasts exactly until such time as one of the users closes the tab with chat. And does not open it again in a day. Or in a month. Or a year later. What does the developer need to do so that the user sees everything new that has happened during his absence? And preferably so as not to hang the browser.
Serialization and numbering - two whales of message history
The main part of the mechanism is the sequential numbering of all messages in a conversation. In the
SendMessage event, there is a
seq field that contains a unique message identifier. The identifier is unique within a conversation and is constantly increasing. Accordingly, if we closed the browser page, opened it after a year and want to find out which new messages came during this time, all that needs to be done is to store somewhere the sequence id of the last message received, and after opening the page request the missing messages from the cloud. Or, for example, the last few dozen, and load the rest, only if the user decided to view the log.
An auxiliary detail is serialization. The SDK is high-level and works with objects. For example, if we want to receive new messages for a conversation, then we first need to get an object for this conversation using
getConversation , and then a message using the method of this object,
retransmitEvents')
But if we just loaded the page, where did we get the objects from? We have a bunch of id's stored in prudently localStorage. And the objects will have to be created, and each such object creation is a request to the cloud to get the necessary information.
The solution is the built-in mechanism for serializing objects using the
toCache and
create ... FromCache methods , which create a JSON representation of the object internals and can restore an object from such JSON without accessing the server. And JSON can be stored in localStorage, instantly restoring hundreds of channels and a million messages when the page loads.
Million posts - and JavaScript or localStorage will not burst?
With web pages, unlike desktop and mobile applications, everything is complicated. When a user commands “close tab” or “close browser”, the “beforeunload” event is triggered, to which you can subscribe. The messages “you have unsaved data” in google docs is a string that the developer returned from the handler. Previously, it was possible even to make alert'y in it, but the scam page “your browser is blocked, give money” gently hinted to the browser developers that you shouldn’t allow much in the “beforeunload” handler.
Nevertheless, modern browsers give our code a few seconds before showing such a message and the user starts to worry:
And in a few seconds it is quite possible to serialize several hundred conversations with a million messages into localstorage. But here it is important to remember that by default localStorage is limited to 5-10 megabytes, and even less for mobile browsers or if the user delved into the settings.
Best practices for nothing to burst
If you are making a new “Skype for Web” and are planning a really large number of messages from your users, then to store serialized objects it is better to use indexedDB, which is now supported by all popular browsers. There are a lot more quotas there by default and you can explicitly ask the user using the Quota Management API and specific browser pieces.
The second point is that if in a conversation a lot of messages have been accumulated since the last visit, it will be reasonable to request the last several dozen from the server and load the rest only if the user has scrolled the log. It turns out a kind of "reverse infinite scroll" - new elements will not arise from the bottom, as when scrolling the Facebook page, but from above.
This year, we plan to significantly expand our messaging, adding control via HTTP and webbooks. This will allow developers to do integration with other messengers, program management of messages like “chat with operators” and other interesting things.