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

Api 服务器在Rails中发送的事件不是异步传递的,api,server-sent-events,ruby-on-rails-6,puma,Api,Server Sent Events,Ruby On Rails 6,Puma,我正在尝试编写一个API,它使用Rails 6中的ActionController::Live::SSE交付服务器发送的事件。为了理解如何最好地编写测试,我从以下几个方面开始: my_controller.rb: class MyController < ApplicationController include ActionController::Live def capture response.headers['Content-Type'] = 'text/event

我正在尝试编写一个API,它使用Rails 6中的
ActionController::Live::SSE
交付服务器发送的事件。为了理解如何最好地编写测试,我从以下几个方面开始:
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
更容易看出这一点的是,在我的测试中,尝试解析来自服务器的响应失败:

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,"domain":"some.random.com","id":2216354,"path":"/flummoxer/","protocol":"https"}
'

我的服务器是彪马,所以

我做错了什么?如果你要求的话,我会提供任何可能有用的额外信息

更新:建议将
-N
Accept:text/event stream
头添加到请求中。这样做并不会改变我上面描述的行为——直到调用
response.stream.close
才发送对请求的响应

更新2:我还尝试破解
SSE#write
方法,在
Mutex::ConditionVariable
上调用
broadcast()
,强制发送消息。这是可行的,因为它会立即发送数据,但有一个副作用,即curl请求认为流已关闭,因此不会发送进一步的消息,而这不是流


更新3:我还修改了
development.rb
以包括
config.allow\u concurrency=true
,如图所示。上述行为没有改变。

我在一个基本的“出书”Rails 5 SSE应用程序中遇到了类似的问题。问题是机架更新导致流缓冲。更多信息请点击此处,并通过包括

config.middleware.delete Rack::ETag


在config/application.rb中

我希望您注意到,您在
睡眠
-ing时阻塞了线程,因此Puma在此期间无法执行任何与线程相关的工作,例如发送响应等。。。如果将阻塞调用移动到另一个线程或适当的调度程序,您可能会有更好的体验。另外,我写道,所以当我谈到服务器内部时,这不是巧合。非常感谢您的回复。据推测,这不应该影响是否发送响应,因为
#write()
方法已经返回。还是我遗漏了线程服务器的一些奇怪的方面?上面的执行暂停是为了让我知道(看着它执行
curl
请求)消息是否单独发送。你能提出一个不同的方法来验证它吗?这是一个关于如此小的话题的荒谬的长时间讨论(这个话题仍然是开放的,而且看不到明确的解决方案!)。非常感谢你的侦查!
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,"domain":"some.random.com","id":2216354,"path":"/flummoxer/","protocol":"https"}
'