January18
If you’re doing web development of any substance the first thing you’ll hit is how to avoid users having to wait for things that take ‘a long time’. Like sending emails.
A naive implementation for reset password could be:
- User requests ‘place order’
- Server processes request and sends order details to user’s email account
- User is presented message to this effect
Thing is, (2) could take ages (particularly if you’re using free SMTP remailer services like Gmail where it typically takes 2-4s by design).
What would be nicer is something like this:
- User requests ‘place order’
- Server creates a task to do this in the background
- Server immediately responds with a ‘order details will be sent very shortly’
- User receives order details more or less the same time as in first scenario
Because (3) is shown to the user faster, they can get on and do other things, and also your server’s request processor isn’t held up.
This seems obvious but its amazing how hard this queuing / background processing is to get right (e.g. if its in the background, how do you make sure the context is set up when its run later, etc). I think for a large number of cases, the Ruby on Rails gem ‘delayed_job’ does an incredible job. Check this out:
Original code:
Order.place_order(order_request)
or 100% equivalently in ruby:
Order.send(:place_order, order_request)
With delayed_job, here’s the new code that is run in the background:
Order.send_later( :place_order, order_request )
delayed_job adds this feature to every class in Rails! So sending email is the same:
Mailer.send_later( :deliver_order_confirmation, self )
It’s incredibly well designed because it is so simple. A thing well made indeed. Other parts are simple as well:
- delayed_job only needs a single server but supports more than one very easily (just create new instances)
- As its a plugin adding support to your Rails system is a single command (script/plugin install delayed_job).
Notes
Right now delayed_job is heavily forked on github — there seem to be about 20+ variations. The one that most seem to use is collectiveidea’s branch:
Delated_job or DJ encapsulates the common pattern of asynchronously executing longer tasks in the background.
via collectiveidea’s delayed_job at master – GitHub.
… although for automated testing there is a great feature in hashrocket’s variation that allows you to force the background job to be, well, not background any more with a ’synchrony’ flag. So I’ve used a combination of both. I’m sure this will settle down the coming months.