zmbq
zmbq

Reputation: 39039

Django asynchronous requests

Does Django have something similar to ASP.NET MVC's Asynchronous Controller?

I have some requests that will be handled by celery workers, but won't take a long time (a few seconds). I want the clients to get the response after the worker is done. I can have my view function wait for the task to complete, but I'm worried it will put too much burden on the webserver.

Clarification:

Here's the flow I can have today

def my_view(request):
    async = my_task.delay(params)
    result = async.get()
    return my_response(result)

async.get() can take a few seconds - not too long so that the client can't wait for the HTTP response to get back.

This code might put unnecessary strain on the server. What ASP.NET MVC's AsynchronousController provides, is the ability to break this function in two, something similar to this:

def my_view(request):
    async = my_task.delay(params)
    return DelayedResponse(async, lambda result=>my_response(result))

This releases the webserver to handle other requests until the async operation is done. Once it done, it will execute the lambda expression on the result, giving back the response.

Upvotes: 2

Views: 5570

Answers (2)

AlexA
AlexA

Reputation: 4118

  1. Instead of waiting for request to complete, you can return status "In progress" an then send one more request to check if status has changed. Since you're doing pure lookups, the response will be very fast and won't put much burden on your web server.

  2. You can outsource this specific view/feature to Tornado web server which is designed for async callback. The rest of the site may continue to run on django.

  3. Most likely the solution should be not technical, but in UI/UX area. If something takes long, it's ok to notify user about it if notification is clear.

Upvotes: 2

pynovice
pynovice

Reputation: 7752

Yes, you can do something only when the task completes. You would want to look into something called chain(). You can bind celery tasks in chain:

    chain = first_function.s(set) | second_Function.s(do)

    chain()

These two functions first_function and second_function will both are celery functions. The second_function is executed only when first_function finishes its execution.

Upvotes: 1

Related Questions