Api 服务器在Rails中发送的事件不是异步传递的
我正在尝试编写一个API,它使用Rails 6中的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
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"}
'