Streaming data from Sinatra/Rack application

前端 未结 4 424
说谎
说谎 2020-12-02 21:13

I am trying to stream textual data (XML/JSON) from a Ruby (1.9.1p378) Sinatra (1.0) Rack (1.2.1) application. The suggested solutions (e.g. Is there a way to flush html to t

相关标签:
4条回答
  • 2020-12-02 21:24

    Neither Webrick nor Thin support streaming that way. You could try Mongrel or Unicorn. If you want to use Thin or Rainbows!, you have to hook into the event loop in order to achieve streaming:

    require 'sinatra'
    
    class Stream
      include EventMachine::Deferrable
      def initialize
        @counter = 0
      end
    
      def each(&block)
        if @counter > 10
          succeed
        else
          EM.next_tick do
            yield counter
            each(&block)
          end
        end
      end
    end
    
    get '/' do
      Stream.new
    end
    

    I recently wrote a EventSource implementation that way:

    require 'sinatra'
    
    class EventStream
      include EventMachine::Deferrable
      def each
        count = 0
        timer = EventMachine::PeriodicTimer.new(1) do
          yield "data: #{count += 1}\n\n"
        end
        errback { timer.cancel }
      end
    end
    
    get '/' do
      EventMachine.next_tick do
        request.env['async.callback'].call [
          200, {'Content-Type' => 'text/event-stream'},
          EventStream.new ]
      end
      [-1, {}, []]
    end
    

    If you want to use Webrick for Streaming: here is a patch.

    0 讨论(0)
  • 2020-12-02 21:38

    As Colin mentioned, Goliath can stream response data, as well as incoming (large file uploads). There is an example in the repo for streaming data to the client: https://github.com/postrank-labs/goliath/blob/master/examples/stream.rb

    Instead of a timer, you can easily hook up any other data stream to push data to the client. For example, you can connect an AMQP queue, or any other message queue directly to Goliath and let it act as an HTTP frontend to that data.

    0 讨论(0)
  • 2020-12-02 21:42

    You should definitely take a look at the rack-able Goliath web server. It supports streaming out-of-the-box. I am using it for a firehose style streaming api.

    Goliath is both an app server and a lightweight framework designed to meet the following goals: fully asynchronous processing, middleware support, simple configuration, high-performance, and arguably most importantly, readable and maintainable code.

    0 讨论(0)
  • 2020-12-02 21:43

    Starting with Sinatra 1.3, you could also use the new streaming API:

    get '/evented' do
      stream(:keep_open) do |out|
        EventMachine::PeriodicTimer.new(1) { out << "#{Time.now}\n" }
      end
    end
    
    0 讨论(0)
提交回复
热议问题