- GraphQL AioWS version: 0.2.0
- Python version: Python 3.6.6 (default, Jun 27 2018, 14:44:17)
- Operating System: Debian Stretch
Then I close ws connection to server after subscription some asyncio tasks are not destroyed. If I reload page of my webapp several times, there are a lot of existing tasks. It's possible memory leak.
Example app:
fromaiohttp.webimportApplication, run_app, WebSocketResponsefromgraphql_ws.aiohttpimportAiohttpSubscriptionServerfromgrapheneimportSchema, ObjectType, Field, ID# SchemaclassHistoryRecord(ObjectType):
id=ID()
classQuery(ObjectType):
history=Field(HistoryRecord)
defresolve_history(self, info):
returnHistoryRecord(id='first')
classSubscription(ObjectType):
history=Field(HistoryRecord)
defresolve_history(self, info):
asyncdefresolver(info):
yieldHistoryRecord(id='second')
returnresolver(info)
schema=Schema(query=Query, subscription=Subscription)
# ServerclassServer(AiohttpSubscriptionServer):
asyncdefon_open(self, *args, **kwargs):
print('Connection open')
awaitsuper().on_open(*args, **kwargs)
defon_close(self, *args, **kwargs):
print('Connection close')
super().on_close(*args, **kwargs)
subscription_server=Server(schema)
# WS handlerasyncdefsubscriptions(request):
ws=WebSocketResponse(protocols=('graphql-ws',))
awaitws.prepare(request)
awaitsubscription_server.handle(ws)
returnws# Applicationapp=Application()
app.router.add_get('/ws', subscriptions)
# List tasksfromasyncioimportTask, get_event_loop, sleepfromsysimportgetrefcountfromtimeimporttimeasyncdeftest():
count=0whileTrue:
awaitsleep(15)
count+=1print('. Timer iteration N', count)
tasks=Task.all_tasks()
print('.. Total tasks: %s'%len(tasks))
fortaskinsorted(tasks, key=lambdax: str(x)):
print('... refs={} {}'.format(getrefcount(task), task))
loop=get_event_loop()
loop.create_task(test())
# Fire!run_app(app, host='0.0.0.0', port=8888)Task list after 3 connections. Full log attached.
Connection open
. Timer iteration N 6
.. Total tasks: 14
... refs=4 <Task finished coro=<AiohttpSubscriptionServer._handle() done, defined at /home/gik/src/graphql/graphql-ws/graphql_ws/aiohttp.py:54> result=None>
... refs=4 <Task finished coro=<AiohttpSubscriptionServer._handle() done, defined at /home/gik/src/graphql/graphql-ws/graphql_ws/aiohttp.py:54> result=None>
... refs=4 <Task finished coro=<AiohttpSubscriptionServer.on_connection_init() done, defined at /home/gik/src/graphql/graphql-ws/graphql_ws/aiohttp.py:93> result=None>
... refs=4 <Task finished coro=<AiohttpSubscriptionServer.on_connection_init() done, defined at /home/gik/src/graphql/graphql-ws/graphql_ws/aiohttp.py:93> result=None>
... refs=5 <Task finished coro=<AiohttpSubscriptionServer.on_connection_init() done, defined at /home/gik/src/graphql/graphql-ws/graphql_ws/aiohttp.py:93> result=None>
... refs=6 <Task finished coro=<AiohttpSubscriptionServer.on_start() done, defined at /home/gik/src/graphql/graphql-ws/graphql_ws/aiohttp.py:101> result=None>
... refs=4 <Task finished coro=<AiohttpSubscriptionServer.on_start() done, defined at /home/gik/src/graphql/graphql-ws/graphql_ws/aiohttp.py:101> result=None>
... refs=4 <Task finished coro=<AiohttpSubscriptionServer.on_start() done, defined at /home/gik/src/graphql/graphql-ws/graphql_ws/aiohttp.py:101> result=None>
... refs=6 <Task finished coro=<RequestHandler.start() done, defined at /usr/lib/python3/dist-packages/aiohttp/web_protocol.py:340> result=None>
... refs=5 <Task finished coro=<RequestHandler.start() done, defined at /usr/lib/python3/dist-packages/aiohttp/web_protocol.py:340> result=None>
... refs=4 <Task finished coro=<RequestHandler.start() done, defined at /usr/lib/python3/dist-packages/aiohttp/web_protocol.py:340> result=None>
... refs=5 <Task pending coro=<AiohttpSubscriptionServer._handle() running at /home/gik/src/graphql/graphql-ws/graphql_ws/aiohttp.py:62> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x7fcec832af48>()]> cb=[shield.<locals>._done_callback() at /usr/lib/python3.6/asyncio/tasks.py:688]>
... refs=8 <Task pending coro=<RequestHandler.start() running at /usr/lib/python3/dist-packages/aiohttp/web_protocol.py:376> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at0x7fcec832ab58>()]>>
... refs=6 <Task pending coro=<test() running at ./bin/ex.py:63>>
Connection close
logfile.txt
Then I close ws connection to server after subscription some asyncio tasks are not destroyed. If I reload page of my webapp several times, there are a lot of existing tasks. It's possible memory leak.
Example app:
Task list after 3 connections. Full log attached.
logfile.txt