4

I am running 2 kinds of django web server simultaneously in my architecture, gunicorn(WSGI with worker_class=gevent) and channels(ASGI) respectively. WSGI server is responsible for handling HTTP request and channels is responsible for websocket connections.

There is an API on WSGI server that would run a SQL query, and then trigger sending message to a particular user via websocket. I called async_to_sync to wrap the channel_layer.group_send, but sometimes error occurrs.

Here's the code

def some_view(request):
    # database operations
    # ...
    channel_layer = get_channel_layer()
    async_to_sync(channel_layer.group_send)(
        group_name,
        {
            'type': 'send_function',
            'data': data
        },
    )

Most of the time it works fine, however, sometimes RuntimeError "You cannot use AsyncToSync in the same thread as an async event loop - just await the async function directly." occurred. This happened because there is a running event loop in current thread. I think it's probably that django is reusing threads and each request would initialize an event loop due to async_to_sync.

My first solution is to create event_loop for each request and then call loop.run_until_complete, but it cause another RuntimeError "Cannot run the event loop while another loop is running"

Then I tried to check if there is running event loop before call create event loop, if an event loop is running, get the running loop first, then call running_event_loop.run_until_complete. But it seems stupid and still have a slight chance to cause the same RuntimeError.

Is there any way to solve this problem?

Note that I set DJANGO_ALLOW_ASYNC_UNSAFE to 'true'

0 Answers0