Handling Rails Background and Batch Jobs with BackgrounDRb
Posted by Daniel Butler Tue, 23 May 2006 11:20:00 GMT
Ezra Zygmuntowicz has announced the alpha release of a framework to help you manage long running background tasks in Ruby on Rails applications. Ezra describes it as follows:
BackgrounDRb is a small framework for divorcing long running tasks from Rails request/response cycle. With HTTP it is usually not a very good idea to keep a request waiting for a response for long running actions. BackgrounDRb also allows for status updates that in combination with ajax can render live progress bars in the browser while the background worker task gets completed. The MiddleMan can also be used as a cache. You can store rendered templates or compute intensive results in the MiddleMan for use later.
DRb Progress Bar Movie
DRb Ajax Tail Demonstration Movie
Ezra’s BackgroundDRb Article at brainspl.at
Read more for example code.
Example Worker class code:
class FooWorker
include DRbUndumped
def initialize(options={})
@progress = 0
@results = []
@options = options
start_working
end
def start_working
# Work loop goes inside a new thread so it doesn't block
# rails while it works. A neat way to do progress bars in
# the browser is to have a @progress instance var that is
# initialized to 0 and then gets bumped up by your long
# running task. This way you can poll for the progress
# of your job via ajax and update a client side progress bar.
Thread.new do
# main work loop goes here. do work and update the
# progress bar instance var.
while something
@results << foo(@options)
@progress += 1
break if @progress > 99
end
end
end
def results
@results
end
def progress
puts "Rails is fetching progress: #{@progress}"
@progress
end
endExample controller code:
# start new worker and put the job_key into the session so you can
# get the status of your job later.
def background_task
session[:job_key] = MiddleMan.new_worker(:class => :foo_worker,
:args => {:baz => 'hello!', :qux => 'another arg!})
end
def task_progress
if request.xhr?
progress = MiddleMan.get_worker(session[:job_key]).progress
render :update do |page|
page.replace_html(
'progress',
"<h3>#{progress}% done</h3>" +
"<img src='/images/progress.gif' " +
"width='#{progress * 2}' height='15' />")
if progress == 100
page.redirect_to :action => 'results'
end
end
else
redirect_to :action => 'index'
end
end
def results
@results = MiddleMan.get_worker(session[:job_key]).results
MiddleMan.delete_worker(session[:job_key])
end
BackgrounDRb installs as a plugin, and all code resides within your Rails application. Because it can communicate to remote servers via DRb, you can launch your long-running tasks on other machines if necessary. It looks like it’ll soon become a very useful framework for building Rails front-ends to existing applications, and for handling user interaction with batch processes.
Enjoy.


Ezra has just posted a new release which implements BackgrounDRb as a full-fledged plugin, “complete with rake tasks for installing the start stop scripts, a generator for creating new worker classes, and rake tasks to start and stop the server.”
Any idea when Windows support will be returned?