Fastr - A Web Framework for Ruby

Foreword

Every month I go on a binge and learn something new. The most recent binge resulted in a new web framework, called fastr.

I’ve always used Rails when I needed to create a web application in Ruby, but despite how great it is to code in, the performance and concurrency is not up to par.

Don’t get me wrong — Rails can scale, but it is not inherently very good when it comes to an individual instance’s performance. While this is hopefully changing in Rails 3, I wanted to see what kind of concurrency and performance I could get out of a simple EventMachine web application. Thus, fastr was born.

Fastr's Architecture

Fastr is nothing special. It is an extremely simple MVC style web framework, similar in configuration to Rails.

What makes it different though, is how it handles requests and responses.

The core of fastr runs on an EventMachine reactor, which is basically just a big event loop. EventMachine is very capable of maintaining thousands of connections in one instance. This is great when you want an application that supports Comet and chunked responses. There is very minimal overhead in having thousands of connections that have occasional data flowing through.

EventMachine and Fastr also support the ability to defer a response until a long running task finishes executing. This is nice because it won’t block the rest of the application. The only catch is you are limited to EventMachine’s thread pool size, which I believe defaults to 20. You can always up this number though, if you want.

Routing

The routing is very similar to Rails, an example routes.rb file looks like this:

 router.draw do |route|
        route.for '/:controller/:action'
        #route.for '/home/:action', :action => '[A-Za-z]+'
        #route.for '/test', :to => 'home#index'
 end

Controllers

Controllers are simple, with just a list of actions that are called based on the route. Actions should return a valid Rack response. There are convenience methods in the controller that help in creating Rack responses.

The nice thing about the controllers in Fastr is that you can defer responses with ease. Here is an example of a deferred response:

  def long_running_task
    defer_response(200, {"Content-Type" => "text/plain"}) do |response|
      puts "in our deferred response...now we can do cool stuff!"
      response.send_data("hey\n")

      long_task = proc {
        log.debug "Sleeping for 5 seconds...but this won't block other requests"
        sleep(5)
        log.debug "Finished sleeping, returning response to client."
        return "finished"
      }

      callback = proc { |result|
        log.debug "Callback result: #{result}"
        response.send_data("#{result}\n")
        response.succeed
      }

      response.task(long_task, callback)
    end
  end

The alternative render methods also exist, where you can render a HAML template or just text:

render(:text, "Hello, world!")
render(:haml, :template => "index") # this searches for index.haml in your app/views/ folder

Future

For now, fastr is just a toy framework for me, that I hope to share with anyone interested in learning about building web frameworks.

I intend to start writing some tests as well as making fastr more robust. I don’t mean to displace any other Ruby web framework, but as I learn with fastr I hope to contribute what I learn back to projects like Rails and Sinatra.

Also, I’d like to get em-mysql or equivalent integrated so that you can really enjoy a event-driven web framework — event with database access.

Check out the GitHub page for more examples on getting fastr up and running.

GitHub: http://github.com/chrismoos/fastr


comments powered by Disqus