ProtocolTypeError - took to long to shut down and was killed

I have a DRF app running asgi through Daphne. I’ve been noticing this error occasionally when I do a POST call that runs a potentially long-running process (typically 5-15 seconds but sometimes as long as 60-90 seconds). The error is

 Application instance <Task pending name='Task-164' coro=<ProtocolTypeRouter.__call__()
running at .../virtualenv/django_py39/lib/python3.9/site-packages/channels/routing.py:71>
wait_for=<Future pending cb=[_chain_future.<locals>._call_check_cancel() at /Library/Frameworks
/Python.framework/Versions/3.9/lib/python3.9/asyncio/futures.py:384, <TaskWakeupMethWrapper 
object at 0x107749580>()]>> for connection <WebRequest at 0x1076fdbb0 method=POST uri=/route
/some_other_route clientproto=HTTP/1.1> took too long to shut down and was killed.

my django REST api is pretty much

from rest_framework import generics
from rest_framework.response import Response

class SomeGeneralQueryAPI(generics.GenericAPIView):
    def post(self, request, *args, **kwargs):
        query_resp = self.long_running_query(request)
        resp = Response(json.dumps(query_resp))
        return resp

   def long_running_query(self, req):
         return <something that takes a long time>

Where long_running_query is a call to an external API to gather some other data.
Since it’s possible that the call to the external API could either time out or fail, is there a way for me to handle this where it won’t “take too long to shut down” and throw a warning like the one seen above?

Thanks!

Hi, did you write (or override) a websocket_disconnect method?

It appears that if you don’t raise StopConsumer the server will reach its application close timeout.

check this out
https://channels.readthedocs.io/en/latest/topics/consumers.html#closing-consumers

In this case my http traffic is going through the get_asgi_application() function. I’m not doing any websocket interaction here although I do have channels configured to handle websockets as well.
I’m only raising StopConsumer at the point of a websocket disconnect.

Do I have to create some sort of http consumer that properly handles my REST calls somehow? Or can I call StopConsumer even within the post method should something go wrong?

If you don’t have control over the external API, and you know it isn’t stable in terms of response time, I think you should program some kind of “auto retry” method and handle StopConsumer inside of it.

The exception will still raise as it is stated in Daphne if the task never completes.

This would be the case the external API doesn’t respond at all,
on the other hand, if the API suddenly fails in the middle of the connection, perhaps you could implement some kind of buffer and resume the connection at that point if it fails, although I think there’s some degree of responsibility on the API side to allow you to do so.

Btw im no expert on the subject, just giving you some workaround ideas