ruby-on-railsmongreleventmachinethin

Using EventMachine with Thin


I recently switched from mongrel to thin when upgrading to rails 3. Prior to the switch, we had been using EventMachine without any problem. After switching to thin,whenever EventMachine would be called, the server would bomb and say the variable we return is nil.

From what I understand thin utilizes EventMachine which is probably causing a conflict with the implementation that was used with Mongrel. I haven't worked with EventMachine much but it seems like I need to run EventMachine inside in another instance to separate it from the EventMachine being used by thin. Am I on the right track? How would I go about instantaneous this to run in its own process separate from Thin's EventMachine?

Here is a snippet of the EventMachine we currently have implemented

def connect
  EventMachine.run {
    args, options = { 
     :query => @options[:query],
      :head  => @options[:headers]
    }, {
      :connect_timeout    => @options[:timeout],
      :inactivity_timeout => @options[:timeout]
    }   

    args[:body] = @options[:data] if allow_body?
    args[:redirects] = @options[:redirects] if @options[:redirects]

    http = EventMachine::HttpRequest.new(@uri, options).send(@options[:method], args)

    http.errback  {
      @response = HttpConnection::Response.new(http, false, @options[:logger])

      EventMachine.stop
    }   

    http.callback {
      @response = HttpConnection::Response.new(http, true, @options[:logger])

      EventMachine.stop
    }   
  }   

  return @response
end

Solution

  • Thin already provides and manages an EventMachine reactor, so you don't need to set one up seperately. I don't think you need to embed this code in the EventMachine.run {} block for starters.

    There are a few problems with your approach here. Firstly, the returned @response variable will always be nil, because the EventMachine::HttpRequest happens asynchronously, and will not give you any data until you hit the http.callback {} block. Secondly, in each of the EventMachine::HttpRequest callbacks, you're calling EventMachine.stop. This will have the effect of stopping the thin webserver, which is probably why you're seeing the server bombing.

    If you're trying to run this sort of code within a rails app, you might need to find a way to handle the calls asynchronously, so that the app doesn't hang while waiting for a long-running process to happen. A good approach I've used for this is to use Sinatra, which has an async plugin, allowing you to hold open long-running requests. You can then include this in your rails3 app using rails metal, so that requests to your async/eventmachine code are routed to sinatra.