Search code examples
androidtimepubnub

Chat messages ordering strategy in PubNub


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();
            }

Solution

  • How do I order Chat Messages on multiple devices in multiple timezones?

    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:

    1. Determine the local time (in milliseconds): start = now()
    2. Load the server timetoken: timetoken = http://pubsub.pubnub.com/time/0
    3. Calculate the delay latency for a timetoken request: delay = now() - start
    4. Convert server timetoken into milliseconds: timetoken = timetoken/10000
    5. Add a delay to compensate for latency: 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!" } });