Синатра 1.3 Потоковое с перенаправлением Ruby stdout - PullRequest
0 голосов
/ 24 декабря 2011

Я хотел бы использовать функцию потоковой передачи Синатры, представленную в 1.3, в сочетании с некоторым перенаправлением stdout. По сути, это будет прямая трансляция длительной работы. Я изучил этот вопрос и потоковый пример Синатры в README.

Запуск 1.8.7 на 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 пуст при первом вызове и никогда не выводится в буфер 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.string. StringIO не имеет возможности потоковой передачи?

1 Ответ

1 голос
/ 14 февраля 2012

Я решил эту проблему, обнаружив, что s.string периодически обновлялось с течением времени, поэтому я просто собрал выходные данные в отдельном потоке, захватил различия и вывел их.Похоже, что перенаправление строк не ведет себя как обычный объект ввода-вывода.

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...