Question

I'm building a Sinatra app that uses TweetStream (which listens for Tweets using EventMachine). I would also like the app to serve pages like a normal Sinatra app but it seems like Sinatra can't "listen" for page requests when it's "listening" for Tweets.

Is this something I can fix by using a different server or structuring my app in a different way? I've tried using WebBrick and Thin.

Here is basically what I'm doing:

class App < Sinatra::Base

  # listening for tweets
  @client = TweetStream::Client.new
  @client.track(terms) do |status|
    # do some stuff when I detect terms
  end  

  get '/' do
    "Here's some page content!"
  end

end
Was it helpful?

Solution

You can mount Sinatra apps within eventmachine (providing you you a awebserver that supports EM i.e., Thin). You should then have full access to the EM reactor loop from your Sinatra app, as well as allowing any other EM plugins to run too.

The Sinatra recipes have a good example:

http://recipes.sinatrarb.com/p/embed/event-machine

here is a very stripped down version of the code:

require 'eventmachine'
require 'sinatra/base'
require 'thin'

def run(opts)

  EM.run do
    server  = opts[:server] || 'thin'
    host    = opts[:host]   || '0.0.0.0'
    port    = opts[:port]   || '8181'
    web_app = opts[:app]

    dispatch = Rack::Builder.app do
      map '/' do
        run web_app
      end
    end

    unless ['thin', 'hatetepe', 'goliath'].include? server
      raise "Need an EM webserver, but #{server} isn't"
    end

    Rack::Server.start({
      app:    dispatch,
      server: server,
      Host:   host,
      Port:   port
    })
  end
end

class HelloApp < Sinatra::Base

  configure do
    set :threaded, false
  end

  get '/hello' do
    'Hello World'
  end

  get '/delayed-hello' do
    EM.defer do
      sleep 5
    end
    'I\'m doing work in the background, but I am still free to take requests'
  end
end

run app: HelloApp.new

OTHER TIPS

if you really want to use the tweets streaming feature then you need to run the streaming part as a separate process and write it's results say into a database, then read those records from your sinatra app.

that's how it works the twitter stream listener is a separate thing from your sinatra app and you need some sort of a queue to join them, say redis or db, or something like that.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top