Multi threaded Ruby on Rails actions?
I’m currently making an app that will spit out pdf reports all over the shop. These reports will get kinda big, doing loads of database calls and rendering images. As such it could take 15 seconds or more to render. Making the reports on the fly therefore could be a horrid user experience with unexpected waits and halts (and a nightmare for a server admin).
So my first attempt was batch the process, as the majority of the data that the pdfs render only changes about once a day. The batch process would go through our database and render all the reports and dump them out to file. User access then would be instantaneous. Wonderful!
The problem is that some bits of data can change at any time. For example these reports display a contact name and email address at the top. So if that changed, the pdf wouldn’t reflect this. Not very professional.
To combat this I added a spooling table, where if some data changed a request was added to a table. A script would then run every minute that would process the pending requests.
This is a slightly dumb approach, I know. What I need is two threads. So when the user updates the contact information, one thread would render the html page as usual and the other to render the pdf. The benefit being that the user doesn’t have to wait for the pdf thread to complete.
Ruby can deal with threads but finding information about doing a task like this is tough, let alone with Rails. Any help out there?
Readings
Rails wiki on threads
Ruby Reliable Messaging Gem
Reliable Messaging Rails example
March 23rd, 2007 at 2:17 am
Use a message queue and topic to queue and broadcast your requests around to a cluster of PDF report servers in the background.
http://rubyforge.org/projects/reliable-msg/
March 23rd, 2007 at 10:33 am
Humm interesting. Thanks!
November 16th, 2007 at 3:01 pm
If you haven’t already found the answer to this — which I doubt; you being an enterprising rails developer — have you considered running BackgrounDRb? Building your own threading would be fine, you can use Ruby’s Thread class, but it might have a lot of unintended consequences if you don’t have a very strong background in multithreaded apps.
The other option would be to have a observer that watches for changes and automatically builds pdfs for what it needs to. Could even run these observers in BackgrounDRb for extra points. :P