I'm using Pubnub to publish live messages from a Server to a client (browser page). When using Pubnub, one must abide by their message size constraints, sometimes resulting in the need to chunk the message, send it in pieces, and reconstruct on the client side. Following Pubnub's advice, one can ensure delivery of each chunk of a message if the Pubnub.publish()
function is not called too quickly (i.e. if the message pieces are simply being pumped through a for loop).
The Pubnub Ruby API specifies 3 required arguments in a Pubnub.publish()
, a channel, a message, and a callback function. The callback function shown below is from Pubnub's Ruby examples:
@my_callback = lambda { |message| puts(message) }
pn.publish(:channel => :hello_world,
:message => "hi",
:callback => @my_callback)
The message in the callback (not the "hi" message in the publish), contains the status information of the publish()
call with values like "sent" and "message to large", both of which would be accompanied by a unique identifier.
So somewhere under the Pubnub hood, this callback is getting a .call()
- I'm wondering if there is a way for me to get inbetween this process. More detailed, say I have a message that needs to be broken up into three chunks, I would like for chunk 0 to be sent, and upon receipt of a "sent" status in the callback, I would like to then send chunk 1, etc...
I'm not very familiar with lambda functions and their scopes, and this was my first attempt:
@my_callback = lambda { |message|
puts(message)
Rails.logger.debug("Setting pubnub_do_send to true from callback")
pubnub_do_send = true
}
pubnub_do_send = true
while !pubnub_message.nil?
if pubnub_do_send
#Send pubnub message
#Cut off first chunk of message (this is why I'm testing for nil)
#Set pubnub_do_send to false
Rails.logger.debug("Message #{message_id} chunk #{chunk_id} sent")
pubnub_do_send = false
end
end
This resulted in an utter failure - getting the server completely locked into an infinite while loop because (if I had to guess) pubnub_do_send was never set to true again. Looking at the debug log, I see the first message print ("Message 1 chunk 0 sent") but never the output from the callback function. (Probably because of the infinite while loop it's found itself in)
There must be a clean way to do this, and I'm ok with refactoring code to some extent, chunking up the messages and storing into an array first and then simply looping through the array to send, but I feel like the solution can't be far off, I'm just not too handy with lambda functions and callbacks.
I feel like the solution should look like:
@my_callback = lambda { |message|
puts(message)
send_pubnub_message(message_id, chunk_id, chunk)
}
def send_pubnub_message(message_id, chunk_id, chunk)
#Send pubnub message
#Send message_id, next chunk_id, and next chunk to my_callback
end
But the problem is my_callback
is called by Pubnub when the Pubnub.publish()
gets some status back about the message rather than me directly calling it! (Is there a way for me to insert message_id, chunk_id, and chunk into the callback while still letting pubnub attach its message to the mix? That sounds way wrong, but maybe with Ruby...)
Thanks in advance for all help.