Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails “这是什么原因?”;找不到标识符为“的订阅”;有线电视?_Ruby On Rails_Ruby_Redis_Actioncable - Fatal编程技术网

Ruby on rails “这是什么原因?”;找不到标识符为“的订阅”;有线电视?

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

我正在使用Rails 5.0.0.rc1+ActionCable+Redis构建一个messenger应用程序

我有单通道
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