Handling Rails Background and Batch Jobs with BackgrounDRb
Posted by Daniel Butler Tue, 23 May 2006 11:20:00 GMT
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.

