We are building a chat application in Android and having a hard time deciding the message ordering strategy for the messages. Uptil now, we have been using device time for the sent messages and server time for the received messages. We realised this strategy can fail very easily if the device time is out of sync with server time.
As an alternative, we are planning to use the device time for both sent and received messages to maintain correct ordering. To account for cases, where device time can be incorrectly set, we plan to show a toast to the user if the PubNub timetoken received in the Publish callback is way off from the user's device time. Code snippet below:
Is this an acceptable strategy for the message ordering? Are there better alternatives.
public void successCallback(String channel,
Object message) {
if (channel.equals(getUserChannel())) {
JSONArray messageDetails = (JSONArray) message;
if(messageDetails.length() >2)
try {
long timeToken = Long.parseLong(messageDetails.getString(2));
timeToken = timeToken / 10000;
changeMessageStatus(chatMessage.getMobileId(), Status.SENT);
long diffValue = timeToken - Calendar.getInstance().getTimeInMillis();
if(Math.abs(diffValue) > Constants.TIME_DIFF_THRESHOLD)
{
applicationHandler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), getString(R.string.incorrect_time), Toast.LENGTH_SHORT).show();
}
});
}
Log.d(Constants.TAG,"Diff Time: " + String.valueOf(diffValue));
} catch (JSONException e) {
e.printStackTrace();
}
}
pubnub.unsubscribeAll();
}
PubNub provides a time
API which can be used to synchronize clients (each having its own latency) within a millisecond of each other. This can be done by creating a minimum buffer amount of time (wait time) for which all devices agree to move forward after acknowledging the signal. You can use this Time Sync API to create an Order ID for each message. First you need to store the client delta drift and calculate the current time.
Follow these basic steps to sync devices with independent latencies:
start = now()
timetoken = http://pubsub.pubnub.com/time/0
delay = now() - start
timetoken = timetoken/10000
message_order_id = timetoken + delay
Use message_order_id
to synchronize all devices to fire at a particular clock time. The message_order_id
is essentially your new message OrderID that can be used to render the message on screen. When you publish a chat message, include the message_order_id
as an entry in the dictionary.
message_order_id = timetoken + delay // new message order id
pubnub.publish({ message : { order_id : message_order_id, message : "Hi!" } });