Here is a minimal blueprint to reproduce the issue:

@my_blueprint.route('/my_route', methods=['POST'])
async def my_route() -> Response:

    await asyncio.sleep(5)

    return format_json_response(
        {
            'success': True,
        },
    )

It works perfectly fine when making calls one by one with some delay between the calls. But if making concurrent calls or just making serial calls too fast, it produces the following error:

 Traceback (most recent call last):
    File "[myvenv]lib/python3.8/site-packages/gunicorn/workers/base_async.py", line 55, in handle
      self.handle_request(listener_name, req, client, addr)
    File "[myvenv]lib/python3.8/site-packages/gunicorn/workers/ggevent.py", line 127, in handle_request
      super().handle_request(listener_name, req, sock, addr)
    File "[myvenv]lib/python3.8/site-packages/gunicorn/workers/base_async.py", line 108, in handle_request
      respiter = self.wsgi(environ, resp.start_response)
    File "[myvenv]lib/python3.8/site-packages/flask/app.py", line 2213, in __call__
      return self.wsgi_app(environ, start_response)
    File "[myvenv]lib/python3.8/site-packages/flask/app.py", line 2193, in wsgi_app
      response = self.handle_exception(e)
    File "[myvenv]lib/python3.8/site-packages/flask_cors/extension.py", line 165, in wrapped_function
      return cors_after_request(app.make_response(f(*args, **kwargs)))
    File "[myvenv]lib/python3.8/site-packages/flask/app.py", line 2190, in wsgi_app
      response = self.full_dispatch_request()
    File "[myvenv]lib/python3.8/site-packages/flask/app.py", line 1486, in full_dispatch_request
      rv = self.handle_user_exception(e)
    File "[myvenv]lib/python3.8/site-packages/flask_cors/extension.py", line 165, in wrapped_function
      return cors_after_request(app.make_response(f(*args, **kwargs)))
    File "[myvenv]lib/python3.8/site-packages/flask/app.py", line 1484, in full_dispatch_request
      rv = self.dispatch_request()
    File "[myvenv]lib/python3.8/site-packages/flask_protobuf/api.py", line 91, in dispatch_request
      rv = original_dispatch_request(self)
    File "[myvenv]lib/python3.8/site-packages/flask/app.py", line 1469, in dispatch_request
      return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
    File "[myvenv]lib/python3.8/site-packages/asgiref/sync.py", line 209, in __call__
      raise RuntimeError(
  RuntimeError: You cannot use AsyncToSync in the same thread as an async event loop - just await the async function directly.

Here is some additional environment information:

gevent==23.7.0
flask[async]==2.3.3
gunicorn[gevent]==20.1.0
gunicorn wsgi:app --workers=2 -k gevent

The actual endpoint does some complex async/await parallel processing, but it behaves exactly like this minimal example.

I'm expecting the endpoint to work without any error messages.

1

There are 1 best solutions below

0
TanThien On

I think this issue from async def my_route. It will use AsyncToSync class so it cannot proccess into the main thread which the gevent running.

So, Change the mode gunicorn to gthread to fix it.

gunicorn wsgi:app --workers=2 -k gthread