微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Rails中服务器发送的事件不是异步传递的

如何解决Rails中服务器发送的事件不是异步传递的

我正在尝试编写一个API,该API在Rails 6中使用ActionController::Live::SSE来传递服务器发送的事件。为了理解如何最好地编写测试,我从copying the trivial example seen here开始: my_controller.rb

class MyController < ApplicationController
  include ActionController::Live
  def capture
    response.headers['Content-Type'] = 'text/event-stream'
    sse = SSE.new(response.stream)
    3.times do
      sse.write({message: "Awaiting confirmation ..."})
      sleep 2
    end
    fake_response  = { #The response as hash.
     "annotation_id"=>nil,"domain"=>"some.random.com","id"=>2216354,"path"=>"/flummoxer/","protocol"=>"https",}
    sse.write(fake_response,event: 'successful capture')
  rescue => e
    sse.write(e.message,event: 'something broke: ')
  ensure
    response.stream.close
  end
end

当我向该端点发送curl请求(无论是POST还是GET)时,响应全部以一个块的形式到达,而不是作为单独的响应到达

$ curl -i -X GET -H  "Content-Type: application/json" -d '{"url": "https://some.random.com/flummoxer"}' http://localhost:3000/capture
HTTP/1.1 200 OK
Content-Type: text/event-stream
Cache-Control: no-cache
ETag: W/"a24048695d2feca40232467f0fbb410a"
X-Request-Id: 648a5229-a43d-40d3-82fd-1c4ea6fe19cc
X-Runtime: 24.082528
transfer-encoding: chunked

data: {"message":"Awaiting confirmation ..."}

data: {"message":"Awaiting confirmation ..."}

data: {"message":"Awaiting confirmation ..."}

event: successful capture
data: {"annotation_id":null,"domain":"some.random.com","id":2216354,"path":"/flummoxer/","protocol":"https"}

在我的测试中,尝试解析服务器的响应失败会很容易看出这一点:

MultiJson::ParseError: 783: unexpected token at 'data: {"message":"Awaiting confirmation ..."}

data: {"message":"Awaiting confirmation ..."}

data: {"message":"Awaiting confirmation ..."}

event: successful capture
data: {"annotation_id":null,"protocol":"https"}
'

我的服务器是Puma,所以it's not because I'm using Thin,as seen in this answer

我在做什么错?如果您提出要求,我将提供其他可能有用的信息。

更新:answers to this question建议将-NAccept:text/event-stream标头都添加到请求中。这样做不会改变我上面描述的行为-在触发response.stream.close调用之前,不会发送对请求的响应。

更新2:我还尝试破解SSE#write方法以在broadcast()调用Mutex::ConditionVariable来强制发送消息。从某种意义上说,它可以立即发送数据,但是它具有卷曲请求的副作用,认为该消息流已关闭,因此不会再发送不是流的消息。

更新3:我还修改development.rb使其包含config.allow_concurrency = true,如here所示。上述行为没有任何变化。

解决方法

我遇到了一个基本的“出书” Rails 5 SSE应用程序类似的问题。事实证明,该问题是机架更新导致的流缓冲。 https://github.com/rack/rack/issues/1619此处提供了更多信息,并通过添加

进行了修复

config.middleware.delete Rack :: ETag

在config / application.rb

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。