As you probably noticed already, I use Workling a lot, and I wrote about it a few times (Part 1, Part 2, Part 3). One minor gotcha to be aware of is that you need to make sure you handle it when Workling is too fast. A common use of Workling is to make a call in an after_save method. For example:
class User < ActiveRecord::Base def after_save MyWorker.asynch_geocode_address(:user_id => self.id) end end
class MyWorker < Workling::Base def geocode_address(options = {}) user = User.find(options[:user_id]) user.geocode_address end end
Pretty straight forward, right? Unfortunately, what you will find is that often your worker will get called so fast on create that ActiveRecord hasn’t committed the transaction yet, and User.find will fail. To get around this, you need to write your workers that could be called from after_save/after_create to handle this condition. Instead of the above, you need to do the following:
class MyWorker < Workling::Base def geocode_address(options = {}) retries = 3 begin user = User.find(options[:user_id]) user.geocode_address rescue => err if (retries -= 1) > 0 sleep(0.2) # Give ActiveRecord a chance to save retry end raise err end end end
Now we catch the exception that ActiveRecord throws when it can’t find the new user yet. Waiting a short time and trying a few times gives ActiveRecord a chance to commit the record.
Enjoy asynchronous processing…
Leave a Reply