Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Faking a Streaming Response in Django to Avoid Heroku Timeout

Tags:

pdf

django

heroku

I have a Django app that uses django-wkhtmltopdf to generate PDFs on Heroku. Some of the responses exceed the 30 second timeout. Because this is a proof-of-concept running on the free tier, I'd prefer not to tear apart what I have to move to a worker/ poll process. My current view looks like this:

def dispatch(self, request, *args, **kwargs):
    do_custom_stuff()
    return super(MyViewClass, self).dispatch(request, *args, **kwargs)

Is there a way I can override the dispatch method of the view class to fake a streaming response like this or with the Empy Chunking approach mentioned here to send an empty response until the PDF is rendered? Sending an empty byte will restart the timeout process giving plenty of time to send the PDF.

like image 390
Tom Avatar asked Jul 13 '17 14:07

Tom


1 Answers

I solved a similar problem using Celery, something like this.

def start_long_process_view(request, pk):
    task = do_long_processing_stuff.delay()
    return HttpResponse(f'{"task":"{task.id}"}')

Then you can have a second view that can check the task state.

from celery.result import AsyncResult

def check_long_process(request, task_id):
    result = AsyncResult(task_id)
    return HttpResponse(f'{"state":"{result.state}"')

Finally using javascript you can just fetch the status just after the task is being started. Updating every half second will more than enough to give your users a good feedback.

If you think Celery is to much, there are light alternatives that will work just great: https://djangopackages.org/grids/g/workers-queues-tasks/

like image 179
Mario César Avatar answered Oct 31 '22 07:10

Mario César