我正在使用Pubnub将实时消息从服务器发布到客户端(浏览器页面)。使用Pubnub时,必须遵守其消息大小限制,有时需要对消息进行分块,将其分段发送,并在客户端重建。根据Pubnub的建议,如果没有快速调用Pubnub.publish()
函数(即如果消息片段只是通过for循环泵送),则可以确保传递消息的每个块。
Pubnub Ruby API在Pubnub.publish()
中指定了3个必需参数,一个通道,一个消息和一个回调函数。下面显示的回调函数来自Pubnub的Ruby示例:
@my_callback = lambda { |message| puts(message) }
pn.publish(:channel => :hello_world,
:message => "hi",
:callback => @my_callback)
回调中的消息(不是发布中的“hi”消息)包含publish()
调用的状态信息,其值为“已发送”和“消息为大” “,两者都会附有唯一的标识符。
所以在Pubnub引擎盖的某个地方,这个回调得到.call()
- 我想知道是否有办法让我介入这个过程。更详细的说,我有一条需要分成三个块的消息,我想要发送块0,并且在回调中收到“已发送”状态后,我想发送块1,等...
我对lambda函数及其范围不太熟悉,这是我的第一次尝试:
@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
这导致完全失败 - 让服务器完全锁定在无限循环中,因为(如果我不得不猜)pubnub_do_send再也没有设置为true。查看调试日志,我看到第一条消息打印(“消息1块0发送”),但从未看到回调函数的输出。 (可能是因为它发现了无限的while循环)
必须有一个干净的方法来做到这一点,我可以在某种程度上重构代码,分块消息并先存储到数组中,然后简单地循环遍历数组发送,但我觉得解决方案离我很远,我对lambda函数和回调都不太方便。
我觉得解决方案应该是这样的:
@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
但问题是当my_callback
获得某些关于消息的状态而不是我直接调用它时,Pubnub会调用Pubnub.publish()
! (有没有办法让我将message_id,chunk_id和chunk插入回调,而仍然让pubnub将其消息附加到混合中?这听起来有点不对,但也许是Ruby ...)< / p>
提前感谢您的帮助。
答案 0 :(得分:1)
您不应该尝试在回调中处理消息块状态。它只有一个责任,通知发布的状态。但是,您可以在邮件中插入内容。我可能会创建一个知道它当前状态的消息包装器,并在lambda中发送它,因此您不必跟踪它。我没有测试过以下代码,但这里是我正在谈论的一个例子:
class Message
attr_accessor :id, :message, :chunked_message, :chunk_id
def initialize(id, message)
@id, @message = id, message
chunk_message
end
def current_chunk
@chunked_message[@chunk_id]
end
def next_chunk
@chunk_id += 1
self
end
def more?
@chunked_message.length > chunk_id
end
private
def chunk_message
implement splitting message here
end
end
def send_pubnub_message(message)
pn.publish(:channel => :hello_world,
:message => message.current_chunk
:callback => lambda { |status|
puts(status)
case status[0] // 1 = success, 0 = fail
when 1
send_pubnub_message(message.next_chunk) if message.more?
when 0
handle_pubnub_error(status[1], message)
end
}
end