Heroku with Django, Celery and CloudAMPQ - timeout error

Viewed 669

I am building an online shop, following Chapter 7 in the book "Django 3 by Example." The book was written by Antonio Melé.

Everything works fine in my local machine. It also works well when I deploy it to Heroku.

However, when I try to use Celery and RabbitMQ (CloudAMQP, Little Lemur, on Heroku), the email message the worker was supposed to send to the customer is not sent. The task takes more then 30 seconds and then it crashes:

heroku[router]: at=error code=H12 desc="Request timeout" method=POST

I have created a tasks.py file with the task of sending emails. My settings.py file include the following lines for Celery:

broker_url = os.environ.get('CLOUDAMQP_URL')
broker_pool_limit = 1 
broker_heartbeat = None 
broker_connection_timeout = 30 
result_backend = None 
event_queue_expires = 60 
worker_prefetch_multiplier = 1 
worker_concurrency = 50 

This was taken from https://www.cloudamqp.com/docs/celery.html

And my Procfile is as follows,

web: gunicorn shop.wsgi --log-file -
worker: celery worker --app=tasks.app

Am I missing something?

Thanks!

2 Answers

So fairly familiar with heroku, though not your tech stack. So the general approach to deal with heroku timeout is this:

First, determine exactly what is causing the timeout. One or more things are taking a lot of time.

Now you have 3 main options.

  1. Heroku Scheduler (or one of several other similar addons). Very useful if you can run a script of some sort via a terminal command, and 10 minutes/1 hour/24 hour checks to see if the script needs to be run is good enough for you. I typically find this to be the most straightforward solution, but it's not always an acceptable one. Depending on what you are emailing, an email being delayed 5-15 minutes might be acceptable.
  2. Background process worker. Looks like this is what you are trying to do with Celery, but it's not configured right, probably can't help much on that.
  3. Optimize. The reason heroku sets a 30 second timeout is because generally speaking there really isn't a good reason for a user to wait 30 seconds for a response. I'm scratching my head as to why sending an email would take more than 30 seconds, unless you need to send a few hundred of them or the email is very, very large. Alternatively, you might be doing a lot of work before you send the email, though that raises the question fo why not do that work seperately from the send email command. I suspect you should probably look into the why of this before you try to get a background process worker setup.

After several days trying to solve this issue, I contacted the support department at CLOUDAMQP

They helped me figure out that the problem was related to Celery not identifying my BROKER_URL properly.

Then I came across this nice comment by @jainal09 here. There was an extra variable that should be set in settings.py:

CELERY_BROKER_URL = '<broker address given by Heroku config>'

Adding that extra line solved the problem. Now Heroku is able to send the email correctly.

Related