I have a send mail to all users that send one email per user.
The function works, but I get an ugly error message on the web app. On the logs i get
2012-08-28T12:08:03+00:00 heroku[router]: Error H12 (Request timeout) -> POST afternoon-spring-6294.herokuapp.com/welcome/wall dyno=web.1 queue= wait= service=30000ms status=503 bytes=0
[...]
Sent mail to xxxx@xxxxx.xxxx (1708ms)
2012-08-28T12:08:31+00:00 app[web.1]: Redirected to http://afternoon-spring-6294.herokuapp.com/
2012-08-28T12:08:31+00:00 app[web.1]: Completed 302 Found in 58114ms (ActiveRecord: 8.9ms)
Is there a workaround (it was triggered by only 33 emails)?
Heroku reaps all process that run longer than 30s, which means almost any batch email through something like mailgun or sendgrid will get killed with the H12 error.
There’s a couple of basic ways to handle, but all involve making things more asynchronous. Heroku worker processes can run indefinitely — or at least FAR longer than 30s.
The traditional option is to use a queue — delayed_job is dead simple and only needs a database to back it. Resque is also cool but requires Redis to be added to the mix. There are also MANY more sophisticated options but delayed_job is dead simple. Railscasts is probably your friend here to figure out how to do it.
Another option is to use a worker process to handle the email tasks directly. For example, you can use a worker to send email in batches every X minutes using a rake task. This is sort of queue without all the overhead. Let’s say you need to send a batch of invitations, you write invitations with an unsent status to a table, then have a rake task pop the first one off and send it, repeat until done. You’d be basically reimplementing a simple queue but might feel more comfortable.
Personally I’d put in delayed_job until I needed something more powerful.