Sinatra 1.3 Streaming w/Ruby stdout 重定向 [英] Sinatra 1.3 Streaming w/ Ruby stdout redirection

查看:43
本文介绍了Sinatra 1.3 Streaming w/Ruby stdout 重定向的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用 1.3 中引入的 Sinatra 的 Streaming 功能以及一些 stdout 重定向.它基本上是一个长时间运行的工作的实时流输出.我查看了 this question 和自述文件中的 Sinatra 流示例.

I would like to use Sinatra's Streaming capability introduced in 1.3 coupled with some stdout redirection. It would basically be a live streaming output of a long running job. I looked into this question and the Sinatra streaming sample in the README.

在 OSX 上运行 1.8.7:

Running 1.8.7 on OSX:

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... <br>\n"
    sleep 1
    out << "...part two... <br>\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 在第一次调用时是空的,它永远不会输出到输出缓冲区.我不太确定正确的顺序是什么,希望得到任何建议.

So this bit of code prints out the first three strings properly, and blocks while the method_that_prints_text executes and does not print anything to the browser. My feeling is that stdout is empty on the first call and it never outputs to the out buffer. I'm not quite sure what the proper ordering would be and would appreciate any suggestions.

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

I tried a few of the EventMachine implementations mentioned in the question above, but couldn't get them to work.

更新

我尝试了一些与在新线程中运行该方法的方法略有不同的方法,并按照 这里...

I tried something slightly different to where I had the method run in a new thread, and override STDOUT for that thread as described here...

而不是上面的 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.string.StringIO 没有流式传输能力吗?

With the ThreadOut module listed in the link above, this seems to work a bit better. However it doesn't stream. The only time something is printed to the browser is on the final line out << s.string. Does StringIO not have the capability to stream?

推荐答案

我最终解决了这个问题,发现 s.string 随着时间的推移会定期更新,所以我只是在一个单独的线程并抓住差异并将它们流式传输出来.似乎字符串重定向的行为不像普通的 IO 对象.

I ended up solving this by discovering that s.string was updated periodically as time went on, so I just captured the output in a separate thread and grabbed the differences and streamed them out. It appears as though string redirection doesn't behave like a normal IO object.

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

这篇关于Sinatra 1.3 Streaming w/Ruby stdout 重定向的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆