Skip to content

asyncio.sleep on an endpoint blocks other requests to that same endpoint #3082

@cnicodeme

Description

@cnicodeme

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

I was trying to implement a semaphore system to allow only a certain amount of requests at the same time, but I discovered that adding a await asyncio.sleep(5) in an endpoint and opening that endpoint twice, even without a semaphore going, would wait for the first request to finish before accepting the second request.

Here's a proof of concept

Code snippet

from sanic import Sanic
from sanic.response import text
import asyncio

app = Sanic("MyHelloWorldApp")

@app.get('/test')
async def test(request):
    print('got a request, waiting')
    await asyncio.sleep(5)  # simulate long processing
    print('    finished!')
    return text('done')

if __name__ == "__main__":
    app.run(port=5000, dev=True, workers=10)

Expected Behavior

We should be able to open 10 tabs to /test and have the first message; "got a request, waiting" displayed immediately here, then wait only 5 seconds and have the 10 tabs ending at the same moment.

But what happens is that the first tabs write "got a request, waiting", waits for 5 seconds. The other tabs wait for loading but show nothing in the terminal. Then, the first tab ends, showing "finished!" and the second tab only starts showing "got a request, waiting".

Important: I purposely set 10 workers to ensure there was not only one thread running, which could have been the reason why it was stuck.

--- More details ---

Adding a second endpoint, with the exact same code, but at "/test2" (and adding a "[2] - " before each print to differentiate) shows that opening "/test" and then "/test2" right after shows the two requests working at the same time. (The terminal shows "got a request, waiting" and right after "[2] - got a request, waiting"). Then both waits 5 seconds and then shows "finished!" and "[2] - finished!" at almost the same time.
Opening a third tab with either "/test" or "/test2" will wait for the same function to finish.

It seems that Sanic blocks at the function (endpoint) level to finish before running another one.

How do you run Sanic?

Sanic CLI

Operating System

Linux

Sanic Version

25.3.0

Additional context

No response

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions