Apr 17 2008

Merb: render_deferred and render_then_call

Following the post on non blocking merb actions, it's worth mentioning the Merb::ControllerMixin module, its render_deferred and render_then_call methods in particular.

render_deferred accepts a block argument, a proc that will be called outside the dispatch mutex, releasing the merb thread lock.

class MyController < Merb::Controller
  def hello
    render "hello"
  end

  def dont_wait_to_hello
    render_deferred { VerySlow.hello }
  end
end

Calls to /my_controller/hello, subsequent to requests to /my_controller/dont_wait_to_hello, will not have to wait for the latter to complete before being served.

As an interesting caveat, because execution of the proc is outside merb's control, any exceptions raised in the block passed to render_deferred will not be rescued and redispatched, which suggests that custom error handling needs to be in place.

render_then_call accepts two arguments, a string that will be returned immediately as a response to the client and a block to be called after the string has been returned.

class MyController < Merb::Controller
  def receive_order
    render_then_call("Your pizza is in the oven.") do
      bake_pizza
      deliver_pizza
    end
  end
end

In this case, the specified message will be immediately returned, while the long running proc will be scheduled and executed by Mongrel, allowing orders to keep coming through a single application instance.