DjangoChannelsGraphqlWs
DjangoChannelsGraphqlWs copied to clipboard
Notify subscriptions on closed socket
Hello,
I need to run some cleanup code when a clent unsubscribes or disconnects. Function similar to unsubscribed(root, info, *args, **kwds)
for the case when a client disconnects would be perfect. Is this possible?
Dear @jordanmarkov,
GraphqlWsConsumer
has on_connect
method to handle the connection event. Probably we should add on_disconnect
there to handle disconnect, e.g. to cleanup something. What do you think? Will this address your need?
Hello @prokher ,
Not really. I would need the arguments for the subscription. I came up with some not really good solution, but it works for my use case. The problem is it uses private members:
class GraphQLWsConsumer(channels_graphql_ws.GraphqlWsConsumer):
# ...
async def disconnect(self, code):
self._assert_thread()
for sid in self._subscriptions:
subinf = self._subscriptions[sid]
await self._run_in_worker(subinf.unsubscribed_callback)
await super().disconnect(code)
# ...
class MySubscription(channels_graphql_ws.Subscription):
class Arguments:
arg1 = graphene.String(required=True)
@staticmethod
async def subscribe(_root, _info, arg1):
# setup
@staticmethod
async def unsubscribed(_root, _info, arg1):
# cleanup
Something along these lines would be perfect, possibly with another callback, but I don't really care in this case if the client has disconnected or unsubscribed.
We really need this as well, we have some tidy up to do when a client disconnected on a per subscription based, right now we're trying to hack it together using the functions above, but it would be much nicer to be baked into the library.
So it is not possible at the moment?
My use case is that I need to set the user as offline for a specific chatroom, therefore accessing the arguments of the subscription.
It would be good to have the on_disconnect in the consumer as well. But for this specific use case, it won't work unless I have access to the subscription payload.
Meanwhile, I implemented the solution from above.
This is effectively what we've done, incase it helps someone
class GraphQLWsConsumer(channels_graphql_ws.GraphqlWsConsumer):
async def disconnect(self, code: int) -> None:
"""
This handles firing off the unsubscribe functions on subscriptions
when a client is disconnected, e.g. when they close the browser
See https://github.com/datadvance/DjangoChannelsGraphqlWs/issues/62
"""
self._assert_thread()
# Fire of a GQL Stop (and therefore unsubscribe) for any active subscriptions
# This is necessary as the library doesnt do this by default.
for sid in self._subscriptions.copy():
await self._on_gql_stop(sid)
await super().disconnect(code)