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