Adventures in BackgroundRb

We’ve been asked to produce some “nice” reports in PDF for a client, and getting it all done has been quite an adventure. We use Ruport for the reporting, which unfortunately means we also need to learn quite a bit about PDFWriter to get everything looking spiffy, and the report rendering does take a while, but we had it all working in a controller yesterday and things were looking good. Then we deployed the application to EngineYard.

The first thing that happened was that we got timeout errors that looked like this (courtesy of ExceptionNotifier):

A Mongrel::TimeoutError occurred in reports#cost_detail_pdf:
Mongrel timed out this thread: shutdown
/usr/lib64/ruby/gems/1.8/gems/mongrel-1.1.3/lib/mongrel.rb:221:in `within'

The support folks at EngineYard suggested that we shouldn’t be running PDF generation from within our controller, and that we should use something like background job, but since we wanted to report status as the job proceeded and we only had a small number of jobs, we went with BackgroundRb instead. (If you care about the difference, look for ‘Backgroundrb and Bj serve different purposes’ in this thread).

BackgroundRb works great once you get it going, but there were examples in the documentation that simply didn’t work for me. Here’s what worked for me in the end:

In my controller:


  MiddleMan.new_worker(:worker => :cost_detail_pdf_worker, :job_key => current_user.id)
  MiddleMan.ask_work(:worker => :cost_detail_pdf_worker, :job_key => current_user.id,
                                          :worker_method => :build_report,
                                          :data => [session[:production_id], file_name])

and my worker:


class CostDetailPdfWorker  calculated_report, :template => :default)
    register_status("Finished Rendering")
    File.open(file_path, "w") do |file|
      file << pdf
    end
    register_status("File available")
  end

end

The next part of the adventure was getting this running on our Slicehost slice. Unfortunately, BackgroundRb requires Ruby 1.8.5, and we only had 1.8.4 (on Ubuntu 6.06 LTS). Apt-get for Ubuntu 6.06 doesn’t include Ruby 1.8.5, so I needed to install Ruby 1.8.5 from source using these excellent instructions.

Unfortunately, I also needed to reinstall all our gems to go with the new version of Ruby. This was mostly stragithforward, except for Postgres. The postgres gem wouldn’t build the native extensions, failing to find pg_config. These instructions were close, but before that would work I also needed to do “apt-get install libpq-dev” (you might also need libpgsql-ruby and/or libpgsql-ruby11.8, but I already had those installed).

Ok, looks pretty good now. I started the backgroundrb server manually as a test, and could produce my pdf files, so the next step was to move to our production environment at Engineyard. This was the first time I tried to stop and start the BackgroundRb using Capistrano – unfortunately you can’t simply repeat the command lines in your Capistrano tasks. Fortunately, there’s also a description of some tasks that do work (make sure you use the start task in the comments at the end of post).

All in all, a nice outcome but with much more pain than I would have liked.

~ by Steve Hayes on March 12, 2008.

4 Responses to “Adventures in BackgroundRb”

  1. Hmm, sad but true.
    Often after each release I will forget to update example workers and hence you may not be able to run those damn workers. Can you send me a patch for them?

  2. Sorry, I didn’t keep precise track of the things that *didn’t* work for me, and to be fair I’m not sure if it’s my own fault or not. What I couldn’t get to work were the examples using MiddleMan.worker, like this one from the documentation: “MiddleMan.worker(:billing_worker).charge_customer(current_customer.id)”

  3. I did mention libpq-dev in the article – Glad you got it working though :)

  4. Dick,

    I wouldn’t have realised I needed libpq-dev at all except for your article! I noted that I needed to do an “apt-get” for Ubuntu neophytes like myself who need stuff to be explicit :-)

    Thanks,
    Steve

Leave a Reply