8

The publish callback in PubNub API returns with a message like below -

[1,"Sent","13729639808030640"]

But this does not give any indication as to for which message this callback is for. In case of publish error, the first value in the return array will be 0. But how do you find out which message to re-publish?

The publisher can be publishing messages at a high rate and not waiting to receive the callback before publishing another message. So when the callback is invoked the publisher might have already published 10 more messages.

Serhii Mamontov
  • 4,942
  • 22
  • 26
user1935449
  • 307
  • 1
  • 2
  • 10
  • Good question and you'll want to set this up on many different ways. Also it depends on which SDK you are using. – Stephen Blum Jul 08 '13 at 20:34
  • i know this is an old question but it's not yet answered by @PubNub and i'm having the same dilemma as of the moment. I'm on android but the platform should not matter. – klambiguit Jun 22 '14 at 16:31
  • Is first-in, first-out tracking acceptable for you @klambiguit ? The responses, error or not, will never come out of order. – Geremy Jun 24 '14 at 03:51
  • If the "responses, error or not will never come out of order" is 100% reliable, then yeah. creating a queue for pending messages is the way to go to i think. But i'd like to confirm with you if this is the best practice for pubnub in terms of keeping track of pending messages. – klambiguit Jun 24 '14 at 17:32

3 Answers3

3

PubNub REST API provide JSONP format as well. You can create map of "callback function" identifiers to actual messages and when processing completed, you can obtain reference on original message using "callback function" identifier from response.
For example:

https://pubsub.pubnub.com/publish/demo/demo/0/iosdev/m_2c453/%22Hello%20world2%22  

As you can see, there is m_2c453 in URI, it will be used by server in response:

m_2c453([1,"Sent","14034711347326358"])

And here we know, that m_2c453 has been used to send "Hello world" message.
But, I think platform dependent PubNub SDK should handle all this for you.

Serhii Mamontov
  • 4,942
  • 22
  • 26
  • Also, keep in mind, even if you rapid fire publishes, all responses will come back from the server in the order they were issued... you'll never get an out-of-order response on the same connection you published on. – Geremy Jun 22 '14 at 21:12
  • thank you for your quick response,as mentioned, I'm using the android sdk and it only returns the JSONArray message and not the one with the jsonp format. how do you do that in android? – klambiguit Jun 23 '14 at 02:22
0

Transferred here since it's too long for a message reply.

In reply with @Geremy, so if message 1,2,3,4,5 will be sent, i'll get a publish callback in 1,2,3,4,5 order? there won't be a case where a response will fail in say 2 and 4? In that case, if we'll continue in the notion that we get an ordered response, this would mean that a response failed to arrive for messages 4 and 5 instead of 2 and 4. Might I suggest to the pubnub team that they add a fourth data in the JSONArray they return, it would contain the id field in the message that was published ( if there is such a data e.g. { "id":123, message:"hello"} ), if there's is none, obviously the returned id would be null or empty string.

klambiguit
  • 527
  • 1
  • 3
  • 14
  • 1
    Yes, you should get back the responses (good or bad) in the order they were sent. – Geremy Jun 23 '14 at 17:48
  • So maintaining a pending message queue and dequeing when a publish callback is called would keep track pending messages. – klambiguit Jun 23 '14 at 23:34
  • 1
    you should really emphasize this on your documentation since this is a very important feature, and an obvious one to have. – klambiguit Jun 24 '14 at 01:39
0

I faced a similar challenge. I wanted to queue messages while the device is offline, and then send them on reconnect. In the callback i needed a way of knowing which message was sent to remove it from the queue. I came up with this solution:

function sendData(channel, data, callback) {
  Pubnub.publish({
    channel: channel,
    message: data,
    callback : callback
  });
}

//This code is placed within the "reconnect" callback of the subscription
if ($localStorage.chatQueue.length) {
  for (var i = 0; i < $localStorage.chatQueue.length; i++) {
    sendData(
      $localStorage.chatQueue[i].channel,
      $localStorage.chatQueue[i].data,
      function(){
        console.log("arguments");
        console.log(arguments);
        console.log("this");
        console.log(this);
        index = $localStorage.chatQueue.indexOf(this);
        console.log("Message in offline queue sent, index = "+index);
        if (index > -1) {
          $localStorage.chatQueue.splice(index, 1);
        }
      }.bind($localStorage.chatQueue[i])
    );
  }
}

The trick is binding this in the callback function to the message object. It seems to work. I guess one could also just bind the i variable which would give a direct pointer to the message in the queue.

I was inspired by this answer in another question: https://stackoverflow.com/a/19472945/3319392

Community
  • 1
  • 1
Jette
  • 2,459
  • 28
  • 37