Sinatra 1.3 Streaming w / Ruby stdout重定向

我想使用1.3中引入的Sinatra的Streamingfunction以及一些stdout重定向。 它基本上是一个长期工作的实时流输出。 我在自述文件中查看了这个问题和Sinatra流式传输示例。

在OSX上运行1.8.7:

require 'stringio' require 'sinatra' $stdout.sync = true module Kernel def capture_stdout out = StringIO.new $stdout = out yield out ensure $stdout = STDOUT end end get '/' do stream do |out| out << "Part one of a three part series... 
\n" sleep 1 out << "...part two...
\n" sleep 1 out << "...and now the conclusion...\n" Kernel.capture_stdout do |stream| Thread.new do until (line = stream.gets).nil? do out << line end end method_that_prints_text end end end def method_that_prints_text puts "starting long running job..." sleep 3 puts "almost there..." sleep 3 puts "work complete!" end

因此,这段代码正确打印出前三个字符串,并在method_that_prints_text执行时阻塞,并且不向浏览器打印任何内容。 我的感觉是stdout在第一次调用时是空的,它从不输出到out缓冲区。 我不太确定正确的排序是什么,并希望得到任何建议。

我尝试了上面问题中提到的一些EventMachine实现,但无法让它们工作。

UPDATE

我尝试了一些与我在新线程中运行方法略有不同的东西,并覆盖该线程的STDOUT,如此处所述……

而不是上面的Kernel.capture_stdout ……

 s = StringIO.new Thread.start do Thread.current[:stdout] = s method_that_prints_text end.join while line = s.gets do out << line end out << s.string 

通过上面链接中列出的ThreadOut模块,这似乎更好一些。 但它不会流。 唯一一次打印到浏览器的是最后一行out << s.stringStringIO没有流式传输function吗?

我最终通过发现随着时间的推移定期更新s.string来解决这个问题,所以我只是在一个单独的线程中捕获输出并抓住差异并将它们流出来。 看起来字符串重定向的行为与正常的IO对象不同。

 s = StringIO.new t = Thread.start do Thread.current[:stdout] = s method_that_prints_text sleep 2 end displayed_text = '' while t.alive? do current_text = s.string unless (current_text.eql?(displayed_text)) new_text = current_text[displayed_text.length..current_text.length] out << new_text displayed_text = current_text * 1 end sleep 2 end