ruby - 从流 block 写入文件

标签 ruby asynchronous sinatra thin puma

开发一个 Web 服务,有时需要返回大文件,并希望它快速向客户端发送一些内容,这样客户端就不会在等待数据开始时超时。 stream 似乎很适合这个,但我遇到了问题。

愚蠢的例子:

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

这工作正常:

$  curl http://localhost:4567/path
   Hello,
   World!

但是我有一个服务写入的辅助日志,并且尝试将文件 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

现在我明白了:

$ curl http://localhost:4567/path
curl: (18) transfer closed with outstanding read data remaining

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

那么,如果我想将某些内容写入流 block 内的输出流以外的其他位置,该怎么办?

最佳答案

不确定这是否是最好的解决方案,但使用异步 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

关于ruby - 从流 block 写入文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32298635/

相关文章:

ruby-on-rails - Rails 未定义方法 `[]' 为 nil :NilClass

mysql - 为我的 Rails 应用添加数据库索引

ruby-on-rails - 使用Sinatra,Thin,Rails和Rack::Cascade的Rack::Session:Cookie错误

ruby - MongoDB Ruby 驱动程序 - `synchronize' : can't be called from trap context

ruby - Ruby 1.9.2 中 `File.read` 中的可选参数

javascript - 您如何或如何使用 firebase 有效地处理错误?

dataframe - 在 Julia 中与 @sync @async 并行

javascript - 这段 AngularJS 代码的目的是什么?

ruby - Sinatra/Rack 因 url 中的非 ascii 字符而失败

css - 在 Sinatra 中提供静态文件时出现问题