Skip to content

Responses are rendered using sync_to_async #58

@cfra

Description

@cfra

What is happening

adrf implements all the machinery for ViewSets and other DRF Views to be called in an async context. ✨

These views then often return a rest_framework.response.Response to be rendered by one of DRF's renderers, dependinng on the outcome of the content negotiation.

The rendering of these responses is done using a mechanism called "deferred rendering" that is implemented in Django's django.core.handlers.base.BaseHandler._get_response_async.

This mechanism checks for the presence of a render method in the Response returned by the view, and if it is present, it
will call this method to render the response.

DRF's Response object subclasses Django's django.template.response.SimpleTemplateResponse, keeping its render method, which is sync.

This causes the Django's _get_resonse_async method to call the rendering like this:

response = await sync_to_async(
    response.render, thread_sensitive=True
)()

Meaning that the rendering of responses returned by async adrf views is dispatched to another thread, and as this is happening with thread_sensitive=True being set to 1, it also means that not only are we switching to a different thread, but also we are serializing this process, so that only one request at a time can render a response.

What should happen

Ideally, adrf would implement a subclass of DRF's Response class which implements render as a coroutine, allowing the full request/response cycle of adrf to happen in an async way.

Otherwise, it would be good to at least document this behavior, so users know what kind of async concurrency they can expect while using adrf.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions