We are using Strawberry to build our GraphQL server and have noticed a possible issue when running tests with pytest using an aiohttp test client to open a websocket and subscribe using the new graphql-transport-ws protocol. We get the follow warning after the tests have finished:
Task was destroyed but it is pending!
task: <Task pending name='Task-169' coro=<BaseGraphQLTransportWSHandler.handle_connection_init_timeout() running at /home/testApp/venv/lib64/python3.8/site-packages/strawberry/subscriptions/protocols/graphql_transport_ws/handlers.py:82> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x7f3c0f9452b0>()]>>
I have taken a look into the code based on this message and I think I have found out what is happening. Essentially an asyncio.sleep()
task is created and run (here). The default time for the sleep is passed in as 60 secs from the GraphQLView instantiation. After the 60 sec sleep this method just checks whether the init_connection message was received. The 60 sec asyncio.sleep()
is not a problem when actually running the server as the server runs for long enough for this time to elapse, or it is killed. However in the test scenario we create a subscription, check the results and then the tests complete, closing the event loop, which all takes less than 60 secs and hence we get the warning that the sleep task was 'destroyed but it it pending!'.
As a work-around we create a custom GraphQLView and set the connection_init_wait_timeout
to a much smaller value (e.g. 5 sec). This stops the warning as the asyncio.sleep()
task can complete in this time, before we close the event loop.
Question: We were just wondering whether there is a reason for a default connection_init_wait_timeout of 60 secs that we have missed?
I also wonder whether there may be a better way of managing the long asyncio.sleep()
task to check the connection_init_received
status. Here are 2 suggestions that might improve the behaviour:
connection_init message
has been received with a short sleep in between and timeout if we do not receive it after 60 secs. This will cause the task to complete as soon as the connection_init message
has been received instead of waiting the arbitrary 60 secs. It also means we do not have a long asyncio.sleep()
task.asyncio.sleep(60)
task is still running and cancels it if it is.Any thoughts/feedback appreciated. Thanks!
Pay now to fund the work behind this issue.
Get updates on progress being made.
Maintainer is rewarded once the issue is completed.
You're funding impactful open source efforts
You want to contribute to this effort
You want to get funding like this too