ActionController :: Live与SSE一起无法正常工作 [英] ActionController::Live with SSE not working properly

查看:128
本文介绍了ActionController :: Live与SSE一起无法正常工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在一个项目中的Rails 4.0.1中使用实时流,但是我看到了问题...

I'm trying to use Live Streaming in Rails 4.0.1 in one project but I see problems...

我有这个动作:

def realtime_push
    response.headers['Content-Type'] = 'text/event-stream'

    sse = SSE.new(response.stream)

    d = Domain.find(params[:domain_id])

    begin
      loop do
        backlinks = d.backlinks.page(params[:page]).per(10)
        pagination = render_to_string(:partial => 'backlinks/pagination', :layout => false, :locals => { :backlinks => backlinks })
        sse.write({ :html => pagination }, :event => 'pagination')
        sleep 1
      end
    rescue IOError
      # When the client disconnects, we'll get an IOError on write
      logger.debug "DISCONNECTED"
    ensure
      sse.close
    end
end

当我启动Puma并尝试获取更新时:

When I start Puma and try to get updates:

curl http://localhost:3000/domains/16/backlinks/realtime_push

卷曲立即返回,没有任何输出.

curl immediately returns with no output.

卷曲标题:

HTTP/1.1 200 OK
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-UA-Compatible: chrome=1
Content-Type: text/event-stream
Cache-Control: no-cache
X-Request-Id: 1a07be2f-de8d-4ca8-87d0-eee2787ea649
X-Runtime: 0.250782
Transfer-Encoding: chunked

Puma日志显示:

Started GET "/domains/16/backlinks/realtime_push" for 127.0.0.1 at 2013-11-08 12:22:30 +0100
  ActiveRecord::SchemaMigration Load (0.7ms)  SELECT "schema_migrations".* FROM "schema_migrations"
Processing by BacklinksController#realtime_push as */*
  Parameters: {"domain_id"=>"16"}
  Domain Load (1.9ms)  SELECT "domains".* FROM "domains" WHERE "domains"."id" = $1 LIMIT 1  [["id", "16"]]
   (3.3ms)  SELECT COUNT(*) FROM "backlinks" WHERE "backlinks"."domain_id" = $1  [["domain_id", 16]]
  Rendered backlinks/_pagination.haml (60.6ms)
   (0.6ms)  SELECT COUNT(*) FROM "backlinks" WHERE "backlinks"."domain_id" = $1  [["domain_id", 16]]
  Rendered backlinks/_pagination.haml (36.0ms)
   (0.8ms)  SELECT COUNT(*) FROM "backlinks" WHERE "backlinks"."domain_id" = $1  [["domain_id", 16]]
  Rendered backlinks/_pagination.haml (37.5ms)
   (0.8ms)  SELECT COUNT(*) FROM "backlinks" WHERE "backlinks"."domain_id" = $1  [["domain_id", 16]]
  Rendered backlinks/_pagination.haml (35.6ms)
   (0.7ms)  SELECT COUNT(*) FROM "backlinks" WHERE "backlinks"."domain_id" = $1  [["domain_id", 16]]
  Rendered backlinks/_pagination.haml (38.7ms)
   (0.7ms)  SELECT COUNT(*) FROM "backlinks" WHERE "backlinks"."domain_id" = $1  [["domain_id", 16]]
  Rendered backlinks/_pagination.haml (37.0ms)

所以这些事情很奇怪:

  • 卷曲没有输出
  • 日志说它分页了6次
  • 日志中没有"DISCONNECT"消息

有什么想法吗?如果我注释掉sse.write上方的两行并返回一些文本而不是分页内容,那么它将起作用...

Any ideas? If I comment out the two lines above sse.write and return some text instead of pagination contents, it works...

这是SSE课程:

class SSE
  def initialize io
    @io = io
  end

  def write object, options = {}
    options.each do |k,v|
      @io.write "#{k}: #{v}\n"
    end
    @io.write "data: #{JSON.dump(object)}\n\n"
  end

  def close
    @io.close
  end
end

推荐答案

这是render_to_string中的错误.

This is a bug in render_to_string.

修复此问题的猴子补丁(实际上不能解决问题-见下文):

Monkey patch to fix this (that actually doesn't fix the problem - see below):

def render_to_string(*)
  orig_stream = response.stream
  super
ensure
  if orig_stream
    response.instance_variable_set(:@stream, orig_stream)
  end
end

来源: http://blog.sorah.jp /2013/07/28/render_to_string-in-ac-live

更新:仅出现 即可解决此问题……尽管这将导致控制器实际发送数据,但出于某种原因,JavaScript的接收端仍不会收到事件通知,请参见此处: SSE(服务器发送的事件)不起作用

UPDATE: this only appears to fix the problem... although it will cause the controller to actually send the data, the receiving end in JavaScript for some reason still won't get notified of events, see here: SSE (Server-sent events) not working

这篇关于ActionController :: Live与SSE一起无法正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆