Friday, May 05, 2017

.deliver_later not working in rake tasks in development for a Rails 5 app

I was just working on a rake task in a Rails 5.0.1 application that sends out emails. I was using the default setup of the :async adapter for ActiveJob (development mode). I was also using the letter_opener gem in development so that emails would pop up in my browser rather than be sent.

Everything looked good when I ran the task with each email using .deliver_now.

In order to let the task finish quickly, I switched the rake task so that each email it generates is enqueued with .deliver_later rather than .deliver_now.

I could see the emails getting enqueued by ActiveJob:

[ActiveJob] Enqueued ActionMailer::DeliveryJob ...

but no emails were popping up in letter opener.

It turns out that the problem was that I didn't understand how :async works. Basically, what's going on is that :async is an in memory queue that only lasts as long as the process that creates it lives. With a rake task, the emails get enqueued correctly (in memory), but then the task ends and the memory queue gets cleared out. But that happens before any processing time has been given to the ActiveJob thread.

To test that things are working in development, any of the following will work:
  • Use .deliver_now
  • Add a sleep(5) to the end of your rake task (just for manual testing ... delete that before you commit)
  • Switch to a different ActiveJob adapter that stores the jobs in some durable queue / db and runs as a separate process from your rake task


Post a Comment

Subscribe to Post Comments [Atom]

<< Home