[英]Write to file from stream block
Working on a web service that sometimes needs to return large files, and want it to send something to the client quickly so the client doesn't time out waiting for the start of the data.处理有时需要返回大文件的 Web 服务,并希望它快速向客户端发送某些内容,以便客户端不会因等待数据开始而超时。
stream
seemed perfect for this, but I ran into a problem. stream
似乎很适合这个,但我遇到了一个问题。
Dumb example:愚蠢的例子:
get '/path' do
status 200
headers 'Content-Type' => 'text/plain'
stream do |out|
sleep 1
out << "Hello,\n"
sleep 1
out << "World!\n"
end
end
This works fine:这工作正常:
$ curl http://localhost:4567/path
Hello,
World!
But I have a side log that the service writes to, and trying to mix File I/O with the streaming API doesn't work at all:但是我有一个服务写入的侧日志,并且尝试将文件 I/O 与流 API 混合根本不起作用:
get '/path' do
status 200
headers 'Content-Type' => 'text/plain'
File.open '/tmp/side-log', 'a' do |lf|
stream do |out|
lf.puts "Woo!"
sleep 1
out << "Hello,\n"
sleep 1
out << "World!\n"
end
end
end
Now I get this:现在我明白了:
$ curl http://localhost:4567/path
curl: (18) transfer closed with outstanding read data remaining
Puma doesn't indicate any problems on the server side, but Thin exits entirely: Puma 没有表示服务器端有任何问题,但 Thin 完全退出:
hello2.rb:13:in `write': closed stream (IOError)
from hello2.rb:13:in `puts'
from hello2.rb:13:in `block (3 levels) in <main>'
from vendor/bundle/gems/sinatra-1.4.6/lib/sinatra/base.rb:437:in `block (2 levels) in stream'
from vendor/bundle/gems/sinatra-1.4.6/lib/sinatra/base.rb:628:in `with_params'
from vendor/bundle/gems/sinatra-1.4.6/lib/sinatra/base.rb:437:in `block in stream'
from vendor/bundle/gems/sinatra-1.4.6/lib/sinatra/base.rb:403:in `call'
from vendor/bundle/gems/sinatra-1.4.6/lib/sinatra/base.rb:403:in `block in each'
from vendor/bundle/gems/eventmachine-1.0.8/lib/eventmachine.rb:1062:in `call'
from vendor/bundle/gems/eventmachine-1.0.8/lib/eventmachine.rb:1062:in `block in spawn_threadpool'
[1]+ Exit 1 ruby hello2.rb
So what should I do if I want to write something out to someplace other than the output stream from inside the stream block?那么如果我想从流块内部向输出流以外的地方写一些东西,我该怎么办?
Not sure if this is the best solution, but using the asynchronous em-files
gem worked for me, even in Puma (which I understand is not EventMachine-based):不确定这是否是最好的解决方案,但使用异步
em-files
gem 对我有用,即使在 Puma 中也是如此(我理解它不是基于 EventMachine 的):
require 'em-files'
get '/path' do
status 200
headers 'Content-Type' => 'text/plain'
EM::File.open '/tmp/side-log', 'a' do |lf|
stream do |out|
lf.write "Woo!\n"
sleep 1
out << "Hello,\n"
sleep 1
out << "World!\n"
end
end
end
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.