Ruby on rails “这是什么原因?”;找不到标识符为“的订阅”;有线电视?
我正在使用Rails 5.0.0.rc1+ActionCable+Redis构建一个messenger应用程序 我有单通道Ruby on rails “这是什么原因?”;找不到标识符为“的订阅”;有线电视?,ruby-on-rails,ruby,redis,actioncable,Ruby On Rails,Ruby,Redis,Actioncable,我正在使用Rails 5.0.0.rc1+ActionCable+Redis构建一个messenger应用程序 我有单通道ApiChannel和许多动作。有一些“单播”操作->请求一些东西,得到一些东西,以及“广播”操作->做一些事情,将有效负载广播到一些连接的客户端 我不时从这里得到RuntimeError异常:无法找到标识符为(…)的订阅。 这可能是什么原因?在什么情况下我可以得到这样的例外?我花了相当多的时间调查这个问题(并将继续这样做),任何提示都将不胜感激 似乎与此问题有关: Rail
ApiChannel
和许多动作。有一些“单播”操作->请求一些东西,得到一些东西,以及“广播”操作->做一些事情,将有效负载广播到一些连接的客户端
我不时从这里得到RuntimeError
异常:无法找到标识符为(…)的订阅。
这可能是什么原因?在什么情况下我可以得到这样的例外?我花了相当多的时间调查这个问题(并将继续这样做),任何提示都将不胜感激 似乎与此问题有关: Rails回复订阅时的某种竞争条件已经创建,但实际上还没有完成 作为一个临时解决方案,在建立订阅后添加一个小的超时解决了这个问题
不过,还需要做更多的调查 此错误的原因可能是您订阅和发送消息的标识符不同。我在Rails 5 API模式下使用ActionCable(使用gem'devise_token_auth'),我也遇到了同样的错误: 订阅(错误): 发送消息(错误): 出于某些原因,ActionCable要求您的客户端实例应用相同的标识符两次—订阅和发送消息时: /var/lib/gems/2.3.0/gems/actioncable-5.0.1/lib/action\u-cable/connection/subscriptions.rb:74
def find(data)
if subscription = subscriptions[data['identifier']]
subscription
else
raise "Unable to find subscription with identifier: #{data['identifier']}"
end
end
这是一个活生生的例子:我实现了一个消息传递子系统,用户在其中以实时模式获取未读消息通知。在订阅时,我并不真的需要通讯员,但在发送消息时,我需要
因此,解决方案是将对应的从标识符散列移动到数据散列:
发送消息(正确):
这样错误就消失了
这是我的未读频道
代码:
class UnreadChannel < ApplicationCable::Channel
def subscribed
if current_user
unread_chanel_token = signed_token current_user.email
stream_from "unread_#{unread_chanel_token}_channel"
else
# http://api.rubyonrails.org/classes/ActionCable/Channel/Base.html#class-ActionCable::Channel::Base-label-Rejecting+subscription+requests
reject
end
end
def unsubscribed
# Any cleanup needed when channel is unsubscribed
end
def process_unread_on_server param_message
correspondent = param_message["correspondent"]
correspondent_user = User.find_by email: correspondent
if correspondent_user
unread_chanel_token = signed_token correspondent
ActionCable.server.broadcast "unread_#{unread_chanel_token}_channel",
sender_id: current_user.id
end
end
end
若您想稍后调用MESSAGE命令,则必须首先调用SUBSCRIBE命令。两个命令必须具有相同的标识符哈希(此处为“通道”)。有趣的是,subscribed
hook是不需要的(!)-即使没有它,您仍然可以发送消息(订阅后)(但是没有subscribed
hook,没有人会收到消息)
另一个有趣的地方是,在subscribed
hook中,我使用以下代码:
stream_from "unread_#{unread_chanel_token}_channel"
显然,未读香奈儿令牌可以是任何东西——它只适用于“接收”方向
因此,订阅标识符(如\'channel\':\'UnreadChannel\'
)必须被视为未来消息发送操作的“密码”(例如,它仅适用于“发送”方向)-如果要发送消息,(首先发送订阅,然后)再次提供相同的“通行证”,否则您将得到所描述的错误
更重要的是——它实际上只是一个“密码”——正如你所看到的,你实际上可以向任何你想要的地方发送信息:
ActionCable.server.broadcast "unread_#{unread_chanel_token}_channel", sender_id: current_user.id
奇怪吧
这一切都相当复杂。为什么不在?FYI中描述,这已经被修复,这正是我的问题。谢谢你说得这么清楚。我遇到了完全相同的问题。
class UnreadChannel < ApplicationCable::Channel
def subscribed
if current_user
unread_chanel_token = signed_token current_user.email
stream_from "unread_#{unread_chanel_token}_channel"
else
# http://api.rubyonrails.org/classes/ActionCable/Channel/Base.html#class-ActionCable::Channel::Base-label-Rejecting+subscription+requests
reject
end
end
def unsubscribed
# Any cleanup needed when channel is unsubscribed
end
def process_unread_on_server param_message
correspondent = param_message["correspondent"]
correspondent_user = User.find_by email: correspondent
if correspondent_user
unread_chanel_token = signed_token correspondent
ActionCable.server.broadcast "unread_#{unread_chanel_token}_channel",
sender_id: current_user.id
end
end
end
def signed_token string1
token = string1
# http://vesavanska.com/2013/signing-and-encrypting-data-with-tools-built-in-to-rails
secret_key_base = Rails.application.secrets.secret_key_base
verifier = ActiveSupport::MessageVerifier.new secret_key_base
signed_token1 = verifier.generate token
pos = signed_token1.index('--') + 2
signed_token1.slice pos..-1
end
stream_from "unread_#{unread_chanel_token}_channel"
ActionCable.server.broadcast "unread_#{unread_chanel_token}_channel", sender_id: current_user.id