无法获得动作控制器::实时与活动支持很好地玩::通知



我一直在寻找使用ActionController :: Live触发服务器端事件的方法,而无需使用轮询。似乎唯一有记录的直播的酒吧/子解决方案是使用Redis,但我真的很想使用目前拥有的堆栈。我遇到了ActiveSupport ::通知,这似乎可以做我想要的。

但是,当我几乎将其使用Redis时,Live会抛出一个ioError,而流则关闭。我没有看到为什么会发生这种情况的任何正当理由。

例如,这可能有效:

def stream
    response.headers['Content-Type'] = 'text/event-stream'
    redis = Redis.new
    redis.subscribe('namespaced:stream') do |on|
        response.stream.write "hello worldn"
    end
    rescue IOError
        # Client Disconnected
    ensure
        response.stream.close
end

但是,当我尝试此操作时,我会收到一个IO错误:

def stream
    response.headers['Content-Type'] = 'text/event-stream'
    ActiveSupport::Notifications.subscribe("process_action.action_controller") do |*args|
        response.stream.write "hello worldn"
    end
    rescue IOError
        # Client Disconnected
    ensure
        response.stream.close
end

我真的不知所措。服务器日志中的任何内容都没有表示实际问题,并且通知订阅否则可行。我可以说,因为即使我遇到了IO错误,也可以在" process_action.action_controller"通知时订阅将字符串放到控制台上。

当没有发生通知时,连接工作正常,但是一旦有通知(我认为应该在流中写" Hello World"),我就会遇到那个愚蠢的IO错误。<<<<<</p>

顺便说一句,我确实计划仪器自己的通知;仅使用现有通知进行测试更容易。

哦,这是我访问使用流控制器方法的路线时终端中发生的情况的副本:

IOError (closed stream):
  /usr/local/lib/ruby/gems/2.0.0/gems/actionpack-4.0.2/lib/action_dispatch/http/response.rb:76:in `write'
  /usr/local/lib/ruby/gems/2.0.0/gems/actionpack-4.0.2/lib/action_controller/metal/live.rb:47:in `write'
  /usr/local/lib/ruby/gems/2.0.0/gems/actionpack-4.0.2/lib/action_controller/metal/live.rb:135:in `rescue in block in process'
  /usr/local/lib/ruby/gems/2.0.0/gems/actionpack-4.0.2/lib/action_controller/metal/live.rb:145:in `block in process'

IOError (closed stream):
  /usr/local/lib/ruby/gems/2.0.0/gems/actionpack-4.0.2/lib/action_dispatch/http/response.rb:76:in `write'
  /usr/local/lib/ruby/gems/2.0.0/gems/actionpack-4.0.2/lib/action_controller/metal/live.rb:47:in `write'
  /home/benjamin/Desktop/workspace/fremote/app/controllers/remotes_controller.rb:25:in `block in show'
  /usr/local/lib/ruby/gems/2.0.0/gems/activesupport-4.0.2/lib/active_support/notifications/fanout.rb:125:in `call'
  /usr/local/lib/ruby/gems/2.0.0/gems/activesupport-4.0.2/lib/active_support/notifications/fanout.rb:125:in `finish'
  /usr/local/lib/ruby/gems/2.0.0/gems/activesupport-4.0.2/lib/active_support/notifications/fanout.rb:40:in `block in finish'
  /usr/local/lib/ruby/gems/2.0.0/gems/activesupport-4.0.2/lib/active_support/notifications/fanout.rb:40:in `each'
  /usr/local/lib/ruby/gems/2.0.0/gems/activesupport-4.0.2/lib/active_support/notifications/fanout.rb:40:in `finish'
  /usr/local/lib/ruby/gems/2.0.0/gems/activesupport-4.0.2/lib/active_support/notifications/instrumenter.rb:36:in `finish'
  /usr/local/lib/ruby/gems/2.0.0/gems/activesupport-4.0.2/lib/active_support/notifications/instrumenter.rb:25:in `instrument'
  /usr/local/lib/ruby/gems/2.0.0/gems/activesupport-4.0.2/lib/active_support/notifications.rb:159:in `instrument'
  /usr/local/lib/ruby/gems/2.0.0/gems/actionpack-4.0.2/lib/action_controller/metal/instrumentation.rb:30:in `process_action'
  /usr/local/lib/ruby/gems/2.0.0/gems/actionpack-4.0.2/lib/action_controller/metal/params_wrapper.rb:245:in `process_action'
  /usr/local/lib/ruby/gems/2.0.0/gems/actionpack-4.0.2/lib/abstract_controller/base.rb:136:in `process'
  /usr/local/lib/ruby/gems/2.0.0/gems/actionpack-4.0.2/lib/abstract_controller/rendering.rb:44:in `process'
  /usr/local/lib/ruby/gems/2.0.0/gems/actionpack-4.0.2/lib/action_controller/metal/live.rb:132:in `block in process'

我很抱歉,如果我误解了任何术语,因为我是SSES和Rails的新手,所以我非常感谢您对此的任何帮助。

编辑:如果您需要知道,我正在使用以下内容:

  • Rails 4.0.2
  • Ruby 2.0.0p353(2013-11-22修订版43784)[i686-Linux]

这是有关此主题的好文章:http://37signals.com/svn/posts/3091-pssst-your-rails-rails-rails-application-has-a-a-a-a-a-secret-secret-secretto-tell to-tell - 你

好吧,您确定Redis和ActiveSupport ::通知具有相同的订阅方法吗?

所以这可能是导致铁轨问题的原因:

  def close
    @response.commit!
    @closed = true
  end

  def write(string)
    raise IOError, "closed stream" if closed?
    @response.commit!
    @buf.push string
  end

您要确保流关闭。写入打电话时,它会通过IOERROR if closed?进行,您要确保发生这种情况。我不是100%确定一切都在发生的,但这似乎是最有可能的罪魁祸首。

所以我回去看一些事情:

在响应的初始化中,我们有:

  self.body, self.header, self.status = body, header, status

这是body=

def body=(body)
  @blank = true if body == EMPTY
  if body.respond_to?(:to_path)
    @stream = body
  else
    synchronize do
      @stream = build_buffer self, munge_body_object(body)
    end
  end
end

@stream =设置为新的Buffer

def build_buffer(response, body)
  Buffer.new response, body
end

所以我认为您的罪魁祸首实际上是您确保response.stream.close。现在,我不确定在写作之前如何调用它。您是先做REDIS,然后测试实时写作,并且它们是否使用相同的响应?如果是这样,您可能会设置要关闭的响应,然后尝试使用它来编写,这将通过ioError。

相关内容

  • 没有找到相关文章